Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Installer un service Windows

Poster un commentaire

Installer un service Windows .Net n’est pas particulièrement difficile, mais pas franchement bien documenté. Disons que l’on finit par y parvenir, mais ce serai tellement mieux avec une vraie procédure.

Justement la voici.

Création du projet

Il y a comme annoncé un modèle Visual Studio:

2014-09-07_00-33-34

 

Le projet Windows Service ressemble à ceci:

2014-09-07_00-36-58

 

Un service Windows ça peut impressionner, mais c’est structurellement très simple: Un hôte qui se charge d’instancier un ou plusieurs services et les lancer. Bref ceci:

/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
    {
        new Service1()
    };

    ServiceBase.Run(ServicesToRun);
}

 

ServiceBase est la classe de base de tout service. La voici, j’ai encadré les méthodes que l’on utilise le plus, leur nom est largement auto descriptif:

2014-09-07_00-50-11

Le code de démarrage créé une table d’instances de ServiceBase et les démarre avec sa méthode Run(). Run enregistre le service dans le Service Control Manager (SCM).

Le SCM est un composant de Windows chargé de gérer le cycle de vie des Services Windows ainsi que leur hébergement. SCM est lancé au boot de Windows. C’est intéressant car ainsi un service Windows peut être lancé sans avoir à démarrer de session.

SCM est un composant RPC, c’est à dire qu’il gère également les accès distants afin de partager un service Windows entre serveurs. La fiche Wikipédia de SCM est intéressante à lire.

Les autres méthodes peuvent être surchargées pour personnaliser le comportement du service durant son cycle de vie du service.

 

Pour la généralité de cet article on va ajouter un deuxième service. On trouvera un item WindowsService.

2014-09-07_12-05-35

Il faudra compléter soi-même le script de démarrage.

ServiceBase[] ServicesToRun;

ServicesToRun = new ServiceBase[]
{
    new Service1(), new Service2()
};
ServiceBase.Run(ServicesToRun);

 

Installation par défaut

Un service Windows se compile certes dans un .exe, mais il ne suffit pas de le lancer pour le démarrer. Il y a un cérémonial:

2014-09-07_01-26-30

 

Pour installer un service il est nécessaire de créer une classe dotée de l’attribut RunInstallerAttribute passée avec la propriété true. Un assistant va s’en occuper.

Double cliquez sur un des services dans le projet, un panneau devrait s’ouvrir:

2014-09-07_12-21-38

Trois choses méritent d’être remarquées. Le panneau lui-même est un conteneur pour des composants.

Le service expose une propriété ServiceName qui permet de lui donner un nom. C’est le nom que l’on verra apparaître tout à l’heure dans le panneau des services Windows. J’ai renommé mes services:

  • PremierService
  • DeuxiemeService

Lee dernier point qui va nous intéresser est la commande Add Installer. C’est elle qui ajoute notre installateur de service. On va l’invoquer pour chaque service.

 

2014-09-07_12-26-51

 

Le projet s’enrichit d’une classe ProjectInstaller. Il s’agit d’une classe qui hérite de System.Configuration.Install.Installer. C’est la classe de base qui permet de créer des processus d’installation personnalisés de services Windows. Je vous conseille de lire la documentation officielle qui est assez claire:

http://msdn.microsoft.com/fr-fr/library/system.configuration.install.installer(v=vs.90).aspx

Personnellement je n’ai jamais eu besoin de surcharger ces méthodes virtuelles, mais on peut avoir besoin de le faire si l’installation par défaut ne vous convient pas.

Par contre on aura certainement besoin d’agir sur les paramètres.

Pour la suite de la discussion, traçons le diagramme de classe de ProjectInstaller:

2014-09-07_14-24-12

Prenez le temps de l’examiner en détails et de le comparer au diagramme précédent.

ServiceProcessInstaller

C’est la classe appelée par les utilitaires d’installation comme InstallUtil. Elle sert au service d’installation à inscrire le service Windows.

 

Elle est commune à tous les services du projet. Le point important est qu’elle doit être décorée de RunInstallerAttribute avec true comme paramètre. Sans cela, l’installation ne fonctionnera pas.

La principale propriété que l’on peu avoir à modifier est Account qui indique le type de compte sous lequel le service va tourner. Les options sont:

  • LocalSystem
  • NetworkService
  • LocalService
  • User

Nous allons choisir cette option qui permet d’utiliser un compte personnalisé.

On a peu de raisons d’appeler directement ses méthodes, mais on peut avoir besoin de surcharger ses événements hérités de Installer qui reflètent le cycle de vie d’une installation:

 

La documentation MSDN vous aidera à en savoir plus:

http://msdn.microsoft.com/fr-fr/library/system.serviceprocess.serviceprocessinstaller(v=vs.110).aspx

ServiceInstaller

Il y en a autant d’instances que de services à installer. Ce sont ses propriétés que l’on peut souhaiter modifier.

La propriété DisplayName désigne le nom sous lequel on verra le service. Si elle n’est pas renseignée, c’est ServiceName vu tout à l’heure qui servira. Je conseille vivement de renseigner Description qui peut d’ailleurs ne contenir que l’url du Wiki ou du projet Github d’où le code est issu. L’essentiel est que ce soit clair.

 

Note: Les classes que nous venons de voir représente le SDK fournit par .Net pour gérer des processus d’installation. Elles ne sont pas réservées aux services Windows. Il est également possible de créer un projet d’installation à part.

 

Note: Avant de procéder à l’insttallation, il faudra créer un login sous lequel le service devra tourner puisque on a choisit Account=User.

 

Je trouve pratique d’accompagner le projet de scripts pour faire le boulot. Je déclare leur propriété Copy to output Directory à Copy always. Comme cela ils sont dans mon /bin.

Les scripts d’installation version 32 bits:
cls
echo Installation et lancement des services…
echo —————————————————
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i WindowsService1.exe
sc start WindowsService1
echo —————————————————
echo Termine

 

Et en version 64 bits:
cls
echo Installation et lancement des services…
echo —————————————————
%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil /i WindowsService1exe
sc start WindowsService1
echo —————————————————
echo Termine

 

Note: j’ai mis en rouge les parties qu’il faudra personnaliser

Notez également que l’installation est transactionnelle, mais pas la désinstallation.

 

Lancez une des versions sous un compte administrateur, la fenêtre suivante va s’ouvrir:

2014-09-07_12-53-51

Deux fichiers de log sont produits en cas de besoin.

Si tout se passe bien on doit voir deux services (PremierService et DeuxièmeService) apparaître dans la fenêtre des services Windows.

Pour désinstaller, je fais également des scripts:

cls
echo Desinstallation et arret...
echo ---------------------------------------------------
sc stop <strong><span style="color: #ff0000;">WindowsService1</span></strong>
%SystemRoot%\Microsoft.NET\Framework\<strong><span style="color: #ff0000;">v4.0.30319</span></strong>\InstallUtil /u <strong><span style="color: #ff0000;">WindowsService1</span></strong>.exe
echo ---------------------------------------------------
echo Termine

Je vous laisse l’adapter en 64 bits sur la base du modèle précédent.

Services liés

Il peut arriver que des services marchent en tandem. Si j’en arrête un, l’autre doit s’arrêter. Par exemple nous allons lier DeuxièmeService à PremierService.

La configuration se fait dans le ServiceInstaller de DeuxièmeService. Nous nous intéressons à la propriété ServicesDependedOn.

2014-09-07_15-33-30

On redéploie.

Vérifiez alors que le démarrage d’un des services démarre l’autre et à l’arrêt:

2014-09-07_15-31-28

 

 

Bibliographie

 

 

 

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s