Création d'une application de type Service Windows

Selkis

Dans ce tutoriel, nous allons voir comment créer un service Windows, ajouter un programme d'installation, l'installer et vérifier son fonctionnement.

- Titre : Création d'une application de type Service Windows

- Auteur : Selkis

- Parution : 16 mars 2005

- Mise à jour : 10 mai 2020

- Licence : Copyright ® 2005 Selkis. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Création du service

- I-A. Préparation du service

- I-B. Ajout des composants nécessaires

- II. Ajout du programme d'installation

- III. Installation et désinstallation du service

- IV. Vérification du service

- V. L'API GlobalMemoryStatus

I - Création du service

Un service Windows est une application de type service s'exécutant généralement en tâche de fond.
L'utilisateur ne peut donc pas interagir avec lui. Il se présente sous la forme d'un exécutable, en grande partie géré par Windows.

Il peut être lancé automatiquement au démarrage de l'ordinateur, arrêter ou redémarrer très simplement. Ces événements sont très souvent inscrits dans un journal d'événements.

But du service : nous allons donc développer un service qui va vérifier toutes les 10 secondes notre mémoire libre par l'utilisation d'une API et émettre un bip si cette dernière descend en dessous des 80 %. Les événements de ce service seront enregistrés dans un journal d'événements.

Pour commencer, nous allons créer un nouveau projet de type Service Windows

L'avantage à utiliser ce modèle est de pouvoir bénéficier par héritage de toutes les fonctionnalités de la classe ServiceBase (fournit une classe de base pour un service qui fera partie d'une application de service).

À la création du projet VS.net va générer automatiquement le code spécifique au lien d'héritage :
Inherits System.ServiceProcess.ServiceBase et donc nous fournir deux procédures :

OnStart() qui permet d'initialiser le processus dont le traitement est effectué périodiquement grâce à un timer.

Cette procédure est activée par Windows et ne doit jamais contenir de boucles infinies

Protected Overrides Sub OnStart(ByVal args() As String)
'Ajoutez ici le code pour démarrer votre service. Cette méthode doit
'permettre à votre service de faire son travail.
End Sub

OnStop() qui permet d'arrêter le service

Protected Overrides Sub OnStop()
' Ajoutez ici le code pour effectuer les destructions nécessaires à l'arrêt 'de votre service.
End Sub

I-A - Préparation du service

Avant toute chose nous devons renommer notre service de Service1 en SMemoire pour nous permettre de mieux l'identifier.

puis, modifier la propriété AutoLog à true, ce qui nous permettra d'inscrire tous les événements liés au service, dans les journaux système.

Pour finir ouvrez la section #region du code,
et dans la procédure Shared Sub Main() modifiez la ligne :

ServicesToRun = New System.ServiceProcess.ServiceBase() {New Service1}

par :

ServicesToRun = New System.ServiceProcess.ServiceBase() {New SMemoire}

I-B - Ajout des composants nécessaires

Sur la page [desing] de SMemoire.vb, ajoutez :

- un contrôle [timer Serveur] nommé : Timer1 dont la propriété interval est définie à 10000 (10 secondes) ;

- un contrôle [EventLog] nommé : Jevent

Le control Jvent de type journal d'événement, va nous permettre d'inscrire dans un journal de log, toute sorte d'information (démarrage du service, arrêt du service, état de la mémoire).

Nous allons donc écrire le code qui va nous permettre de créer ledit journal et de lui affecter en source le nom de notre service.

Dans la procédure Public Sub New() juste en dessous de InitializeComponent() ajoutez le code suivant :

'si le journal de notre application n'existe pas
If Not Jevent.SourceExists("ServiceMemoire") Then
'on le crée
Jevent.CreateEventSource("ServiceMemoire", "JrnlMemoire")
End If
'et on lui indique la source de la création
Jevent.Source = "ServiceMemoire"

- La fonction SourceExists membre de System.Diagnostics.EventLog. Détermine si une source d'événements est inscrite dans l'ordinateur local et prend en paramètre le nom de la source d'événement. Elle retourne vrai si la source est inscrite.

- La méthode CreateEventSource membre de System.Diagnostics.EventLog. Crée un nouveau journal personnalisé sur l'ordinateur local. Elle attend en paramètre le nom de la source grâce à laquelle l'application est inscrite dans l'ordinateur et le nom du journal dans lequel les entrées de la source seront écrites.

- La propriété Source est de type string, elle permet d'obtenir ou de définir le nom de la source à inscrire et à utiliser lors de l'écriture d'entrées dans le journal des événements.

Le control Timer1 va nous permettre grâce a l'événement Elapsed (déclenché en fonction de l'intervalle défini), de lancer la procédure de notre service (dans notre cas, émettre un bip et récupérer la mémoire libre). Il est déclenché ou arrêté par les procédures OnStart() ou OnStop().

Nous allons donc profiter de ces procédures pour inscrire un événement à chaque démarrage et à chaque arrêt du service tout en déclenchant ou en arrêtant notre Timer.

Pour ce faire, modifier les procédures OnStart() et OnStop() comme ci-dessous :

Protected Overrides Sub OnStart(ByVal args() As String)
Jevent.WriteEntry("démarrage du service")
Timer1.Enabled = True
End Sub

Protected Overrides Sub OnStop()
Jevent.WriteEntry("Arrêt du service")
Timer1.Enabled = False
End Sub

Modifier ensuite l'événement Elapsed de notre timer pour qu'il nous récupère les infos concernant notre mémoire.

Private Sub Timer1_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed
'si l'état de notre mémoire est critique alors
If MemoireCritique () = True Then
'on émet un bip et on inscrit dans le journal l'état de notre mémoire libre
Beep()
Jevent.WriteEntry(Str(MemLibre) & "%")
End If

Votre service est créé, vous pouvez maintenant le compiler.

Pour voir l'API et la fonction retournant l'état de notre mémoire, reportez-vous en fin d'article.

II - Ajout du programme d'installation

Un service Windows est une application de type service s'exécutant généralement en tâche de fond.
C'est donc un exécutable dont l'exécution est assurée en grande partie par Windows.
Pour que Windows puisse l'exécuter, il doit être installé, c'est ce que nous allons voir dans ce cours.

Activez la fenêtre de conception SMemoire.vb [Desing] puis cliquez sur F4 pour activer sa fenêtre des propriétés. Au bas de la fenêtre, cliquez sur le lien « Ajouter le programme d'installation », qui va nous permettre de définir les actions liées à l'installation de notre service. Deux composants sont alors créés, l'un pour les paramètres de l'installation du processus, l'autre pour les paramètres liés a l'installation du service.

Dans les propriétés du ServiceInstaller1, il faut vérifier :

- la propriété ServiceName qui doit se nommer Smemoire (le nom du service à installer) ;

- la propriété StartType qui doit être en Automatique (le type de démarrage).

Dans les propriétés du ServiceProcessInstaller1 vérifiez :

- la propriété Account qui doit être sur LocalSystem.

Ouvrez les propriétés de votre projet (projet --> propriété de Smemoire), dans Objet de démarrage et sélectionnez SMemoire.
Vous pouvez maintenant générer et sauvegarder votre projet, vous vous retrouvez avec un fichier ServiceMemoire.exe dans le répertoire bin de votre projet.

III - Installation et désinstallation du service

La création de notre service est réalisée, il ne nous reste plus qu'à le faire prendre en compte par le système d'exploitation en l'installant.
C'est très simple à réaliser, positionnez-vous avec votre explorateur dans le répertoire c:\Windows\Micorsoft.net\Framework\v1.0.xxxx (xxxx représente la version de votre Framework) et lancez le fichier InstallUtil.exe , cela va vous ouvrir une fenêtre de commande, il ne vous reste plus qu'à taper :

InstallUtil « C:\projets\ServiceMemoire\bin\ServiceMemoire.exe »
Le service va s'installer automatiquement.

Pour désinstaller le programme, il suffira de refaire la même procédure, mais de taper :
InstallUtil /u « C:\projets\ServiceMemoire\bin\ServiceMemoire.exe »

IV - Vérification du service

Pour vérifier que notre service est bien installé, il suffit d'ouvrir la console de management des Services de Windows et regarder que notre service est bien présent.
Pour ce faire, cliquez sur démarrer --> panneau de configuration --> Outils d'administration --> Services , puis recherchez votre service (SMemoire)

Vous devez voir ceci :

Notre service est bien présent, l'installation s'est déroulée correctement, nous allons maintenant tester le service en lui-même.

Avant toute chose, n'oubliez pas de démarrer votre service.

Nous allons ensuite consommer volontairement de la mémoire (ouvrez simplement plusieurs applications), et lorsque le seuil de mémoire critique défini par service sera atteint, l'ordinateur émettra un beep et ira inscrire dans le journal événements du service l'état de notre mémoire libre. Il nous suffira de lire ce journal pour voir si les événements ont bien été inscrits.

Pour lire le journal, il faut une fois de plus ouvrir la console de management Windows, mais cette fois-ci, celle de l'Observateur d'événements

Cliquez sur démarrer --> panneau de configuration --> Outils d'administration --> Observateur d'événements

Vous devez apercevoir ceci :

Vous pouvez vous servir des services Windows, pour tout type de surveillance, s'exécutant sur de longues périodes s'exécutant sur leur propre session.

V - L'API GlobalMemoryStatus

Nous permet de récupérer sous forme de structure toute sorte d'information concernant l'état de notre mémoire.
Il se déclare de la façon suivante :

Declare Sub GlobalMemoryStatus Lib "kernel32" (ByRef lpBuffer As MEMORYSTATUS)

'La structure :
Structure MEMORYSTATUS
Dim dwLength As Integer
Dim dwMemoryLoad As Integer
Dim dwTotalPhys As Integer
Dim dwAvailPhys As Integer
Dim dwTotalPageFile As Integer
Dim dwAvailPageFile As Integer
Dim dwTotalVirtual As Integer
Dim dwAvailVirtual As Integer
End Structure

La fonction MemoireCritique()

Private Function MemoireCritique() As Boolean
Dim Memoire As MEMORYSTATUS
GlobalMemoryStatus(Memoire)
MemLibre = Int((Memoire.dwAvailPhys / Memoire.dwTotalPhys) * 100)
If MemLibre < 80 Then
Return True
Else
Return False
End If
End Function

Pour en savoir plus sur les services Windows, vous pouvez consulter :
Applications de service Windows sur le site de Msdn.

Télécharger le code source commenté exemple vb.net ServiceMemoire