Can I manually run a C# class containing a Main() method from a project that is not a console application project? - sharepoint

I am pretty new in .NET\C# (I came from Java) and I have the following doubt.
In my solution I have a project that should be a SharePoint job, something like this in my solution explorer:
I know that this project is deployed as a SharePoint job and it works fine.
Now I have the need to manually perform a specific operation that is in some way related to this job. So my idea was to create this MigrateAttachments class into this project and put a Main() method here, then perform only this class as a script:
namespace XXXMigrationJob
{
class MigrateAttachments
{
static void Main(string[] args)
{
Debug.Print("MigrateAttachments Main() START");
Debug.Print("MigrateAttachments Main() END");
}
}
}
But it seems to me that I can't perform this Main() method as a standalone method and that the only way to do it is to create a brand new Console Application project that will contain this class.
is it true or am I missing something and I can manually run this MigrateAttachements Main() method also into my XXXMigrationJob project?

No you can't really just execute that. It will be in a DLL not an exe. You'll need to bootstrap it somehow.
I would refactor the reusable code into a class library. Then create a console app as you mentioned. Reference the reusable class library and call it.
However if you don't want to create a console app, then the link NineBerry put in discusses calling .net code with PowerShell and Reflection.

Related

Application Initialization in Azure Function Project in VS2017 15.3.4?

In Visual Studio 2017 with the latest update, for azure functions template, I want something where I can initialize like program.cs in webjobs template.
I am trying to create a new subscription with new namespace Manager when application initializes so that I can listen to one service bus topic.
Is there a way to do that? If yes then how?
If you intend to create a subscription that this Function will be triggered on, there is no need to do that manually. Function App will create the subscription based on your binding at deployment time.
For other scenarios (e.g. timer-triggered function), you can do the initialization in a static constructor:
public static class MyFunction1
{
static MyFunction1()
{
var namespaceManager = NamespaceManager.CreateFromConnectionString(connString);
if (!namespaceManager.SubscriptionExists("topic1", "subscription1"))
{
namespaceManager.CreateSubscription("topic1", "subscription1");
}
}
[FunctionName("MyFunction1")]
public static void Run(
// ...
}
Static constructor will run at the time of the first function call.
for azure functions template, I want something where I can initialize like program.cs in webjobs template.
As far as I know, Azure functions do not have good support for this right now. You can find a similar question:
Question:
I have a C# function and want to know if there is any Initialization point. I have dependency injection containers that need initialization
and want to know where to do that.
Mathew's reply
We don't have a good story for this right now. Please see open issue
here in our repo where this is discussed.

Background Task does not run in UWP

I have a UWP application where I want to add background task support for doing certain things while my application is in background.
I am doing exactly as it is mentioned here: https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/create-and-register-a-background-task
I have one separate project for Background Tasks and in my package manifest file I have declared that my app uses background tasks (but "timer" task since I am using TimerTrigger). Code:
BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder { Name = "NotificationUpdater", TaskEntryPoint = "NamespaceOfMyBackgroundTaskInterfaceImplementation.BackgroundTask"};
backgroundTaskBuilder.SetTrigger(new TimeTrigger(15, false));
BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register();
Now, when I launch my app (via Visual Studio), and use Lifecycle Events dropdown to suspend my app, it never executes the Run() method in the BackgroundTask class (implementation of IBackgroundTask interface).
Code inside BackgroundTask class:
namespace NamespaceOfMyBackgroundTaskInterfaceImplementation
{
public sealed class BackgroundTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
//Code to run in the background
}
}
}
As it turned out in the conversation, the problem was in wrong declaration of project type. In should be a Windows Runtime Component.
For the followers, please take a look at this answer, which describes the steps. It answers to Silverlight 8.1, but the process and steps are the same in WinRT and UWP.

Using hooks to trigger a process

I am trying to work out how to use the Hooks and just can't seem to get the syntax correct.
I have built a site using PirahnaCMS that has a blog component and am extending it to call some social plugins and auto post to FB, Twitter etc.
I just can't seem to get the syntax correct though. My app is MVC and I have looked at this section
1.2 ASP.NET MVC
If you're using ASP.NET MVC hooks should be attached in you Global.asax.cs in the Application_Start method, or any other place where you keep you startup code. You attach you hooks with the followin syntax:
protected void Application_Start() {
Piranha.WebPages.Hooks.Menu.RenderItemLink = (ui, str, title, url) => {
str.Append(String.Format("<span>{1}</span>", url, title)) ;
} ;
}
The Hook I believe I want to use is Piranha.WebPages.Hooks.Manager.PostEditModelAfterSave but for the life of me I can't seem to work it out.
All of the hooks are just static delegates that you can attach methods to. In the above example an anonymous method has been assigned to the hook with the syntax:
delegate += (parameters) => { method body }
You could also assign a previously declared method.
delegate += MyMethod
Example skeletons for attaching hooks should be available in the Docs at the official site. If not you can find the hooks in the file:
~/WebPages/Hooks.cs
And all delegates in:
~/Delegates.cs
I hope these URL:s are correct as I'm typing from memory :)
Regards

Ninject dependency injection in SharePoint Timer Job

I have successfully implemented an enterprise SharePoint solution using Ninject dependency injection and other infrastructure such as NLog logging etc using an Onion architecture. With a HttpModule as an Composition Root for the injection framework, it works great for normal web requests:
public class SharePointNinjectHttpModule: IHttpModule, IDisposable
{
private readonly HttpApplication _httpApplication;
public void Init(HttpApplication context)
{
if (context == null) throw new ArgumentException("context");
Ioc.Container = IocContainerFactory.CreateContainer();
}
public void Dispose()
{
if(_httpApplication == null) return;
_httpApplication.Dispose();
Ioc.Container.Dispose();
}
}
The CreateContainer method loads the Ninject modules from a separate class library and my ioc container is abstracted.
For normal web application requests I used a shared static class for the injector called Ioc. The UI layer has a MVP pattern implementation. E.g in the aspx page the presenter is constructed as follows:
presenter = Ioc.Container.Get<SPPresenter>(new Ninject.Parameters.ConstructorArgument("view", this));
I'm still reliant on a Ninject reference for the parameters. Is there any way to abstract this, other than mapping a lot of methods in a interface? Can't I just pass in simple types for arguments?
The injection itself works great, however my difficulty comes in when using external processes such as SharePoint Timer Jobs. It would obviously be a terrible idea to reuse the ioc container from here, so it needs to bootstrap the dependencies itself. In addition, it needs to load the configuration from the web application pool, not the admin web application. Else the job would only be able to run on the application server. This way the job can run on any web server, and your SharePoint feature only has to deploy configurations etc. to the web apllication.
Here is the execute method of my timer job, it opens the associated web application configuration and passes it to the logging service (nlog) and reads it's configuration from the external web config service. I have written code that reads a custom section in the configuration file and initializes the NLog logging infrastructure.
public override void Execute(Guid contentDbId)
{
try
{
using (var ioc = IocContainerFactory.CreateContainer())
{
// open configuration from web application
var configService = ioc.Get<IConfigService>(new ConstructorArgument("webApplicationName", this.WebApplication.Name));
// get logging service and set with web application configuration
var logginService = ioc.Get<ILoggingService>();
logginService.SetConfiguration(configService);
// reapply bindings
ioc.Rebind<IConfigService>().ToConstant(configService);
ioc.Rebind<ILoggingService>().ToConstant(logginService);
try
{
logginService.Info("Test Job started.");
// use services etc...
var productService = ioc.Get<IProductService>();
var products = productService.GetProducts(5);
logginService.Info("Got products: " + products.Count() + " Config from web application: " + configService.TestConfigSetting);
logginService.Info("Test Job completed.");
}
catch (Exception exception)
{
logginService.Error(exception);
}
}
}
catch (Exception exception)
{
EventLog.WriteError(exception, "Exception thrown in Test Job.");
}
}
This does not make the timer jobs robust enough, and there is a lot of boiler plate code. My question is how do I improve on this design? It's not the most elegant, I'm looking for a way to abstract the timer job operation code and have it's dependencies injected into it for each timer job. I would just like to hear your comments if you think this is a good approach. Or if someone has faced similar problems like this? Thanks
I think I've answered my own question with the presenter construction code above. When using dependency injection in a project, the injection itself is not that important, but the way it changes the way you write code is far more significant. I need to use a similar pattern such as command for my SharePoint timer job operations. I'd just like the bootstrapping to be handled better.

Problems using an installclass in a web setup for a web site

I am trying to create a web setup for my web site, and I want to use an installer class to do some custom stuff. I am using VS 2010, and the web site and installer is .NET 3.5.
I have added reference to the installer class project output in the Install section under Custom Actions:
I have also set /targetdir="[TARGETDIR]/" on the CustomActionData for this action.
The InstallScript project is a standard class library (dll).
There is a public class that inherits from Installer class. It overrides the Install method as I have seen been done in several online examples:
using System.Collections;
using System.Windows.Forms;
namespace InstallScript
{
public class MyWebInstaller : System.Configuration.Install.Installer
{
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
var targetDir = Context.Parameters["targetdir"];
if(targetDir==null) targetDir = "No TARGETDIR!";
MessageBox.Show("TARGETDIR:\t" + targetDir);
}
}
}
I would think there should be shown a message box here som time during the install, but it seems like it is never called. No error is shown either. The setup just runs through as if this code was never called.
Anyone have idea of what is wrong?
OK, I found out what was missing.
You need to specify the class with the class attribute RunInstaller(true) for the setup to pick up and actually run the code.
So the class needs to be declared like this:
[System.ComponentModel.RunInstaller(true)]
public class MyWebInstaller : System.Configuration.Install.Installer
{
...

Resources