Créer et configurer un service Windows avec TopShelf et Ninject

Cet article vous montre comment il est possible de créer et configurer facilement un service Windows avec TopShelf et Ninject pour l’injection de dépendances.TopShelf est un package NuGet permettant d’encapsuler une application console classique dans un service Windows.

Ninja Ninject

Cet article vous montre comment il est possible de créer et configurer facilement un service Windows avec TopShelf et Ninject pour l’injection de dépendances.

TopShelf est un package NuGet permettant d’encapsuler une application console classique dans un service Windows.

Ninject est également un package NuGet, c’est un conteneur d’IoC permettant de mettre en place l’injection de dépendances.

Étape 1, créer un projet d’application console et télécharger les packages via la console de gestion.

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

Étape 2, définir des interfaces de services et leurs implémentations dont dépend le service Windows.

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

Étape 3, implémenter un module héritant de ModuleNinject, pour enregistrer les classes concrètes implémentant les interfaces utilisées pour l’injection.

Je recommande le cycle de vie en singleton pour les objets.

using Ninject.Modules;
using TopShelfWindowsService.Services;

namespace TopShelfWindowsService
{
    public class IocModule : NinjectModule
    {
        /// 
        /// Bind Interfaces to implementations for dependancy injection
        /// 
        public override void Load()
        {
            Bind().To().InSingletonScope();
        }
    }
}

Étape 4, implémenter le service Windows en dérivant de l’interface ServiceControl dans l’espace de nom TopShelf.

Je propose également une implémentation d’un timer permettant d’exécuter un service toutes les x secondes, tout en m’assurant qu’un seul service s’exécute à la fois, grâce à la classe statique Monitor.

En dérivant de l’interface ServiceControl, il est obligatoire d’implémenter les méthodes Start et 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);
                }
            }
        }
    }
}

Étape 5, implémenter le point d’entrée au démarrage du service Windows dans une application console grâce à TopShelf.

Nous allons paramétrer ici l’utilisation de Ninject pour l’injection de dépendances, ainsi que le nom du service Windows, sa description, etc.

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");
            });
        }
    }
}

Étape 6, déployer le service Windows.

Une fois que le service Windows est fonctionnel, le déposer (le fichier de config, les .dll, et le .exe généré à la compilation) dans un répertoire sur votre machine.

Puis, en ligne de commande, se positionner sur ce répertoire et lancer l’installation comme suit :

nom_de_l_executable.exe install

Pour le démarrer, procéder comme suit :

nom_de_l_executable.exe start

Vous pouvez également arrêter le service et le désinstaller :

nom_de_l_executable.exe stop
nom_de_l_executable.exe uninstall

Exemples :

Découvrez nos histoires
à succès.

Un projet de développement logiciel?
Contactez-nous!  

Cette entrée a été publiée dans Développement desktop
par Anthony Giretti.
Partager l’article