Les services NT.

Les services NT.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction :

Dans ce chapitre, nous allons aborder les services NT.

Un service est une petite application qui travaille souvent en tache de fond. Les applications services sont enregistrées dans une base de données et gérées par une application le "Service Control Manager". Elles peuvent être lancées automatiquement au démarrage du système ou manuellement par une autre application ou un autre service.

Image non disponible

II. Installation d'un service :

Avant d'être utilisé un service doit être installé. C'est à dire enregistré par le système. C'est le rôle de la fonction CreateService qui reçoit notamment comme paramètres le nom d'enregistrement du service, "MonService" dans l'exemple. Il est enregistré sous forme d'une chaîne de caractère. C'est ce nom qui nous servira à accéder ultérieurement à ce service. Nous avons comme autre paramètre le libellé du service et diverses constantes lui affectant certaines caractéristiques (voir aide API Win32). On peut remarquer que l'on fournie aussi comme paramètre une chaîne de caractère contenant le chemin et le nom de l'exécutable. C'est évidement nécessaire au système pour le localiser. Toutes ces données sont enregistrées dans le registre.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
#include "Windows.h"
#include "Winsvc.h"

int main()
{   
    char strDir[1024];
    SC_HANDLE hSCManager,hService;
    SERVICE_DESCRIPTION SD;
    GetCurrentDirectory(1024,strDir);
    strcat(strDir,"\\MonService.exe");
    hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    hService = CreateService(hSCManager, "MonService", "Mon Service",
       SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
                    SERVICE_ERROR_NORMAL, strDir, NULL, NULL, NULL, NULL, NULL);
    SD.lpDescription = "Ici la description de mon service.";
    ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &SD);
    CloseServiceHandle(hService);

    return 0;
}

III. Désinstallation d'un service :

Voyons brièvement sa désinstallation. Elle s'effectue avec la fonction DeleteService après avoir ouvert le service avec OpenService.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#include "Windows.h"
#include "Winsvc.h"

int main()
{
    SC_HANDLE hSCManager;
    SC_HANDLE hServ;
    hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    hServ=OpenService(hSCManager,"MonService",SERVICE_ALL_ACCESS);
    DeleteService(hServ);
    CloseServiceHandle(hServ);
    CloseServiceHandle(hSCManager);
    return 0;
}

IV. Le service :

Au démarrage d'un service l'exécutable est lancé et sa fonction main exécutée. Dans cette fonction main nous devons remplir un tableau de structure SERVICE_TABLE_ENTRY. Une case du tableau par service (un exécutable peut contenir plusieurs services). Le premier champ de la structure contient la chaîne de caractères identifiant le service. Le deuxième contient un pointeur de fonction sur la fonction principale du service. La dernière structure du tableau doit avoir ses champs à NULL.

Voyons maintenant la fonction d'exécution du service, nommée "ServiceMain" dans l'exemple. Dans cette fonction nous remplissons la structure ServiceStatus de type SERVICE_STATUS. Cette structure prepare l'état que l'on veux donner au service pendant son exécution.

Nous devons aussi implémenter une autre fonction nommée "ServCtrlHandler" dans l'exemple, dont on fournira un pointeur à la fonction RegisterServiceCtrlHandler afin de l'enregistrer. Le Service Control Manager pourra alors lui envoyer des ordres, que cette fonction devra traiter.

Les changements d'état affectés en cours d'exécution dans la structure ServiceStatus doivent être validé par l'appel de la fonction SetServiceStatus. Son premier paramètre est un handle renvoyé par la fonction RegisterServiceCtrlHandler et le second est l'adresse de la structure ServiceStatus. Ensuite on entre dans une boucle qui s'exécute tant que le service est démarré. C'est dans cette boucle que l'on implémente les actions que l'on désire exécuter.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
#include "Windows.h"
#include "Winsvc.h"

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hServiceStatus;
BOOL ServiceStarted=TRUE;
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
void WINAPI ServCtrlHandler(DWORD Opcode);

int main()
{
    SERVICE_TABLE_ENTRY Table[] = {{"Service1",ServiceMain},{NULL,NULL}};
    StartServiceCtrlDispatcher(Table);
    return 0;
}
/******************************************************************************/

void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{ 
    ZeroMemory(&ServiceStatus, sizeof(SERVICE_STATUS));
    ServiceStatus.dwServiceType = SERVICE_WIN32;
    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

    hServiceStatus = RegisterServiceCtrlHandler("MonService", ServCtrlHandler);

    ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 0;

    SetServiceStatus (hServiceStatus, &ServiceStatus);

    ServiceStarted=TRUE;
    while(ServiceStarted)
     {
       Sleep(5000);
       /* Ici la tache à éffectuer. */
     }
}
/******************************************************************************/

void WINAPI ServCtrlHandler(DWORD SCCode)
{
    switch(SCCode)
     {
      case SERVICE_CONTROL_CONTINUE:
          ServiceStatus.dwCurrentState = SERVICE_RUNNING;
          SetServiceStatus (hServiceStatus,&ServiceStatus);
          return;
      case SERVICE_CONTROL_PAUSE:
          ServiceStatus.dwCurrentState = SERVICE_PAUSED;
          SetServiceStatus (hServiceStatus,&ServiceStatus);
          return;
      case SERVICE_CONTROL_STOP:
          ServiceStatus.dwWin32ExitCode = 0;
          ServiceStatus.dwCurrentState = SERVICE_STOPPED;
          ServiceStatus.dwCheckPoint = 0;
          ServiceStatus.dwWaitHint = 0;
          SetServiceStatus (hServiceStatus,&ServiceStatus);
          ServiceStarted=FALSE;
          return;
     }
}

V. Démarrer un service :

Un service peut ce démarrer automatiquement ou manuellement selon sa configuration. Pour le démarrer manuellement par programme, il suffit ouvrir le service et de le démarrer avec la fonction StartService.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
void StartService()
{
    SC_HANDLE SCMan;
    SCMan = OpenSCManager(NULL, NULL, GENERIC_EXECUTE) ;

    SC_HANDLE MonServ;
    MonServ = OpenService(SCMan, "MonService", SERVICE_START );

    StartService(MonServ, 0, NULL);

    CloseServiceHandle(MonServ);
    CloseServiceHandle(SCMan);
}

VI. Arrêter un service :

Un service peut de même être arrêté par programme à l'aide de la fonction ControlService. A savoir que si des services dépendent de votre service, ils doivent être arrêtés avant l'arrêt de votre service.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void StopService()
{
    SERVICE_STATUS_PROCESS ssp;

    SC_HANDLE SCMan;
    SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) ;

    SC_HANDLE MonServ;
    MonServ = OpenService(SCMan, "MonService", SERVICE_STOP );

    ControlService( MonServ, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &ssp ) ;

    CloseServiceHandle(MonServ);
    CloseServiceHandle(SCMan);
}

J'ai omis pour faciliter la comphéantion de tester la validité des valeurs retournées par certaine des fonctions de cet exemple.

J'ai testé les compilations avec C++ Builder et DevC++.

N'hésitez pas à consulter la msdn pour de plus amples renseignements sur les services.

A vos PC.

CGi

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?
  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.
C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.
  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.
DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.
  

Copyright © 2006 CGi. 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.