SHARE:

How to create and configure a Windows service with Topshelf and Ninject?

This article aims to present how it is possible to easily create and configure a Windows service with Topshelf and Ninject using dependency injection.

Topshelf NuGet is a package for encapsulating a classic console application in a Windows Service.

Ninject is also a NuGet package is container IOC to implement dependency injection.

Step 1, create a console application project and download packages via the management console :

PM > Install-Package Topshelf
PM > Install-Package Topshelf.Ninject

Step 2, define / service(s) interface(s) and the implement service to what the windows service depends on :

namespace TopShelfWindowsService.Services
{ 
   public interface IMyService
   { 
       void DoWork(); 
   } 
}
public class MyService : IMyService
{ 
   public void DoWork() 
   { 
      //Do something 
   } 
}

Step 3, implement a module inheriting from “ModuleNinject” in order to register the concrete classes implementing interfaces used for injection

I recommend the lifecycle Singleton for objects, here is how to declare them when recording classes :

using Ninject.Modules; 
using TopShelfWindowsService.Services; 
namespace TopShelfWindowsService
{ 
   public class IocModule : NinjectModule 
   { 
      // Bind Interfaces to implementations for dependancy injection
      public override void Load() 
      { 
         Bind<IMyService>().To<MyService>().InSingletonScope();
      } 
   } 
}

Step 4, implement the windows service deriving from the “ServiceControl” interface in the namespace “Topshelf”

I also propose an implementation of a timer that allows to execute a service all X seconds, while ensuring executes only one service at a time, through the static class “Monitor”.

By implementing the “ServiceControl” interface, it’s mandatory to implement the methods “Start” and “Stop”

using System.Threading; 
using System.Timers; 
using Topshelf; 
using TopShelfWindowsService.Services; 
using Timer = System.Timers.Timer; 
namespace TopShelfWindowsService 
{ 
   public class MyWindowsService : ServiceControl 
   { 
      private Timer _syncTimer; 
      private static object s_lock = new object(); 
      private IMyService _myservice; 
      
      // Constructor 
      public MyWindowsService(IMyService myService) 
      { 
         _myservice = myService; 
      }

      // Starts the windows service
      public bool Start(HostControl hostControl) 
      { 
         _syncTimer = new Timer(); 
         _syncTimer.Interval = 5000; 
         _syncTimer.Enabled = true; 
         _syncTimer.Elapsed += RunJob; 
         return true; 
      }

     // Stops the windows service
     public bool Stop(HostControl hostControl) 
     { 
        _syncTimer.Enabled = false; 
        return true; 
     } 

     // Job runner event, with lock if the job still running
     private void RunJob(object state, ElapsedEventArgs elapsedEventArgs) 
     { 
        // Prevents the job firing until it finishes its job 
        if (Monitor.TryEnter(s_lock)) 
        { 
           try 
           { 
              _myservice.DoWork(); 
           } 
           finally 
           { 
              // unlock the job 
             Monitor.Exit(s_lock); 
           } 
        } 
     } 
   } 
} 

Step 5, implement the entry point at the start of the windows service in a console application through Topshelf :  Here we will set the use Ninject for dependency injection, and the name of windows service, description ….

using Topshelf; 
using Topshelf.Ninject; 
namespace TopShelfWindowsService 
{ 
   class Program 
   { 
      static void Main(string[] args) 
      { 
         HostFactory.Run(x => { 
            x.UseNinject(new IocModule()); 
            x.Service(s => 
            { 
               s.ConstructUsingNinject(); 
               s.WhenStarted((service, hostControl) => service.Start(hostControl)); 
               s.WhenStopped((service, hostControl) => service.Stop(hostControl)); 
            }); 
            x.RunAsLocalSystem(); 
            x.SetDescription("Prototype .NET TopShelf Windows Service"); 
            x.SetDisplayName("Prototype_TopShelf_and_Ninject"); 
            x.SetServiceName("Prototype_TopShelf_and_Ninject"); 
        }); 
      } 
   } 
}

Step 6, deploy the windows service : 

Once the windows service is functional, move it (the config file, dlls and exe generated at compile time) to a directory on your machine.

Then, in the command line, go to the directory that contains dlls and then run the install  as follow :

nom_de_l_executable.exe install

Start it as follow :

nom_de_l_executable.exe start

You can also stop the service and uninstall it :

nom_de_l_executable.exe stop
nom_de_l_executable.exe uninstall

Samples :

topshelf-1

topshelf-2

topshelf-3

Written by

anthonygiretti

Anthony is a specialist in Web technologies (14 years of experience), in particular Microsoft .NET and learns the Cloud Azure platform. He has received twice the Microsoft MVP award and he is also certified Microsoft MCSD and Azure Fundamentals.