I. Introduction▲
Dans ce chapitre, nous allons aborder les services NT.
Un service est une petite application qui travaille souvent en tâche 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.
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 fournit aussi comme paramètre une chaîne de caractères contenant le chemin et le nom de l'exécutable. C'est évidemment nécessaire au système pour le localiser. Toutes ces données sont enregistrées dans le registre.
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.
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 prépare l'état que l'on veut 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és 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.
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 tâche à effectuer. */
}
}
/**
***************************************************************************
*/
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 se démarrer automatiquement ou manuellement selon sa configuration. Pour le démarrer manuellement par programme, il suffit d'ouvrir le service et de le démarrer avec la fonction StartService.
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. À savoir que si des services dépendent de votre service, ils doivent être arrêtés avant l'arrêt de votre service.
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 certaines 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.
À vos PC.