Author: Bertrand Goetzmann
The unit described in this article show how we can start or stop a NT service by
programming, or getting the location of its binary implentation.
Answer:
1 unit SvcUtils;
2
3 // Written by Bertrand Goetzmann (http://www.object-everywhere.com)
4 // Keywords : Service, OpenSCManager, OpenService, CloseServiceHandle,
5 QueryServiceConfig, StartService, QueryServiceStatus, ControlService
6
7 interface
8
9 // This function returns the entire path location of the implementation of the
10 given name service
11 function GetBinaryPathName(const ServiceName: string): string;
12
13 // This function starts the service with the given service name
14 procedure StartService(const ServiceName: string);
15
16 // This function stops the service with the given service name
17 procedure StopService(const ServiceName: string);
18
19 implementation
20
21 uses SysUtils, WinSvc;
22
23 function GetBinaryPathName(const ServiceName: string): string;
24 var
25 SvcMgr, Svc: Integer;
26 QuerySvc: TQueryServiceConfig;
27 BytesNeeded: Cardinal;
28
29 Buffer: PQueryServiceConfig;
30 begin
31 // Establish a connection to the service control manager
32 SvcMgr := OpenSCManager(nil {*MachineName*}, nil {*DatabaseName*},
33 SC_MANAGER_ALL_ACCESS);
34 try
35 if SvcMgr = 0 then
36 RaiseLastOSError;
37
38 Svc := OpenService(SvcMgr, PChar(ServiceName), SERVICE_ALL_ACCESS);
39 if Svc = 0 then
40 RaiseLastOSError;
41 try
42 // Make a call to know the number of bytes needed
43 QueryServiceConfig(Svc, @QuerySvc, 0, BytesNeeded);
44
45 GetMem(Buffer, BytesNeeded);
46 try
47 if not QueryServiceConfig(Svc, Buffer, BytesNeeded, BytesNeeded) then
48 RaiseLastOSError;
49
50 Result := PQueryServiceConfig(Buffer).lpBinaryPathName;
51 finally
52 FreeMem(Buffer);
53 end;
54 finally
55 CloseServiceHandle(Svc);
56 end;
57 finally
58 CloseServiceHandle(SvcMgr);
59 end;
60 end;
61
62 procedure StartService(const ServiceName: string);
63 var
64 SvcMgr, Svc: Integer;
65 ServiceArgVectors: PChar;
66 begin
67 // Establish a connection to the service control manager
68 SvcMgr := OpenSCManager(nil {*MachineName*}, nil {*DatabaseName*},
69 SC_MANAGER_ALL_ACCESS);
70 try
71 if SvcMgr = 0 then
72 RaiseLastOSError;
73
74 Svc := OpenService(SvcMgr, PChar(ServiceName), SERVICE_ALL_ACCESS);
75 if Svc = 0 then
76 RaiseLastOSError;
77 try
78 if not WinSvc.StartService(Svc, 0 {*NumServiceArgs*}, ServiceArgVectors) then
79 RaiseLastOSError;
80 finally
81 CloseServiceHandle(Svc);
82 end;
83 finally
84 CloseServiceHandle(SvcMgr);
85 end;
86 end;
87
88 procedure StopService(const ServiceName: string);
89 var
90 SvcMgr, Svc: Integer;
91 ServiceStatus: _SERVICE_STATUS;
92 begin
93 // Establish a connection to the service control manager
94 SvcMgr := OpenSCManager(nil {*MachineName*}, nil {*DatabaseName*},
95 SC_MANAGER_ALL_ACCESS);
96 try
97 if SvcMgr = 0 then
98 RaiseLastOSError;
99
100 Svc := OpenService(SvcMgr, PChar(ServiceName), SERVICE_ALL_ACCESS);
101 if Svc = 0 then
102 RaiseLastOSError;
103 try
104 // if not QueryServiceStatus(Svc, ServiceStatus) then
105 // RaiseLastOSError;
106 // You can test the ServiceStatus.dwCurrentState field
107
108 if not ControlService(Svc, SERVICE_CONTROL_STOP, ServiceStatus) then
109 RaiseLastOSError;
110 finally
111 CloseServiceHandle(Svc);
112 end;
113 finally
114 CloseServiceHandle(SvcMgr);
115 end;
116 end;
117
118 end.
FAQ:
As do to register my application as a service?
You can register your service application simply by executing it with the /INSTALL
option.
How to pass multi-arguments to StartService?
You can pass some argument with the starting of a service with the call of the
StartService function of the Win32 API. The StartService procedure of the SvcUtils
unit makes a such call with 0 argument :
WinSvc.StartService(Svc, 0 (*NumServiceArgs*), ServiceArgVectors)
What is RaiseLastOSError?
RaiseLastOSError is a function from the SysUtils unit that permits to raise an
exception for the last operating system error or library system error.
I did know how to manage this, but I'm looking for a way to have the list of all
installed services. Do you have a solution for that?
I think that the EnumServicesStatus function from the Windows API is the solution.
The function enumerates services in the specified service control manager database.
The name and status of each service are provided.
The code looks very nice, but one problem; what is it suposed to do?? Any insight
on what this program can do to benefit us would be greatly apprecaited!
On the Windows NT plateform you can look all the installed services by executing
MMC (Microsoft Managment Console). All these services can be handled by this GUI
application (start, stop, suspend, etc.).
This article show the use of some of the Service Functions from the Window API to do the same things by programming
|