Author: Lou Adler
Starting and stopping Windows services
Answer:
When installing certain types of programs it maybe necessary to restart related
services to avoid conflicts. Regardless of the reason why you need to control
services, following functions can help you with starting and stopping services
running on the local computer or on a remote machine.
1 uses WinSvc;
2
3 //
4 // start service
5 //
6 // return TRUE if successful
7 //
8 // sMachine:
9 // machine name, ie: \\SERVER
10 // empty = local machine
11 //
12 // sService
13 // service name, ie: Alerter
14 //
15
16 function ServiceStart(
17 sMachine,
18 sService: string): boolean;
19 var
20 //
21 // service control
22 // manager handle
23 schm,
24 //
25 // service handle
26 schs: SC_Handle;
27 //
28 // service status
29 ss: TServiceStatus;
30 //
31 // temp char pointer
32 psTemp: PChar;
33 //
34 // check point
35 dwChkP: DWord;
36 begin
37 ss.dwCurrentState := -1;
38
39 // connect to the service
40 // control manager
41 schm := OpenSCManager(
42 PChar(sMachine),
43 nil,
44 SC_MANAGER_CONNECT);
45
46 // if successful...
47 if (schm > 0) then
48 begin
49 // open a handle to
50 // the specified service
51 schs := OpenService(
52 schm,
53 PChar(sService),
54 // we want to
55 // start the service and
56 SERVICE_START or
57 // query service status
58 SERVICE_QUERY_STATUS);
59
60 // if successful...
61 if (schs > 0) then
62 begin
63 psTemp := nil;
64 if (StartService(
65 schs,
66 0,
67 psTemp)) then
68 begin
69 // check status
70 if (QueryServiceStatus(
71 schs,
72 ss)) then
73 begin
74 while (SERVICE_RUNNING
75 <> ss.dwCurrentState) do
76 begin
77 //
78 // dwCheckPoint contains a
79 // value that the service
80 // increments periodically
81 // to report its progress
82 // during a lengthy
83 // operation.
84 //
85 // save current value
86 //
87 dwChkP := ss.dwCheckPoint;
88
89 //
90 // wait a bit before
91 // checking status again
92 //
93 // dwWaitHint is the
94 // estimated amount of time
95 // the calling program
96 // should wait before calling
97 // QueryServiceStatus() again
98 //
99 // idle events should be
100 // handled here...
101 //
102 Sleep(ss.dwWaitHint);
103
104 if (not QueryServiceStatus(
105 schs,
106 ss)) then
107 begin
108 // couldn't check status
109 // break from the loop
110 break;
111 end;
112
113 if (ss.dwCheckPoint <
114 dwChkP) then
115 begin
116 // QueryServiceStatus
117 // didn't increment
118 // dwCheckPoint as it
119 // should have.
120 // avoid an infinite
121 // loop by breaking
122 break;
123 end;
124 end;
125 end;
126 end;
127
128 // close service handle
129 CloseServiceHandle(schs);
130 end;
131
132 // close service control
133 // manager handle
134 CloseServiceHandle(schm);
135 end;
136
137 // return TRUE if
138 // the service status is running
139 Result :=
140 SERVICE_RUNNING =
141 ss.dwCurrentState;
142 end;
The procedure to stop a service is similar to starting a service, except for
calling "ControlService()" Win32 function instead of "StartService()", checking for
SERVICE_STOPPED rather than SERVICE_RUNNING and using appropriate control codes.
143
144 // stop service
145 //
146 // return TRUE if successful
147 //
148 // sMachine:
149 // machine name, ie: \\SERVER
150 // empty = local machine
151 //
152 // sService
153 // service name, ie: Alerter
154 //
155
156 function ServiceStop(
157 sMachine,
158 sService: string): boolean;
159 var
160 //
161 // service control
162 // manager handle
163 schm,
164 //
165 // service handle
166 schs: SC_Handle;
167 //
168 // service status
169 ss: TServiceStatus;
170 //
171 // check point
172 dwChkP: DWord;
173 begin
174 // connect to the service
175 // control manager
176 schm := OpenSCManager(
177 PChar(sMachine),
178 nil,
179 SC_MANAGER_CONNECT);
180
181 // if successful...
182 if (schm > 0) then
183 begin
184 // open a handle to
185 // the specified service
186 schs := OpenService(
187 schm,
188 PChar(sService),
189 // we want to
190 // stop the service and
191 SERVICE_STOP or
192 // query service status
193 SERVICE_QUERY_STATUS);
194
195 // if successful...
196 if (schs > 0) then
197 begin
198 if (ControlService(
199 schs,
200 SERVICE_CONTROL_STOP,
201 ss)) then
202 begin
203 // check status
204 if (QueryServiceStatus(
205 schs,
206 ss)) then
207 begin
208 while (SERVICE_STOPPED
209 <> ss.dwCurrentState) do
210 begin
211 //
212 // dwCheckPoint contains a
213 // value that the service
214 // increments periodically
215 // to report its progress
216 // during a lengthy
217 // operation.
218 //
219 // save current value
220 //
221 dwChkP := ss.dwCheckPoint;
222
223 //
224 // wait a bit before
225 // checking status again
226 //
227 // dwWaitHint is the
228 // estimated amount of time
229 // the calling program
230 // should wait before calling
231 // QueryServiceStatus() again
232 //
233 // idle events should be
234 // handled here...
235 //
236 Sleep(ss.dwWaitHint);
237
238 if (not QueryServiceStatus(
239 schs,
240 ss)) then
241 begin
242 // couldn't check status
243 // break from the loop
244 break;
245 end;
246
247 if (ss.dwCheckPoint <
248 dwChkP) then
249 begin
250 // QueryServiceStatus
251 // didn't increment
252 // dwCheckPoint as it
253 // should have.
254 // avoid an infinite
255 // loop by breaking
256 break;
257 end;
258 end;
259 end;
260 end;
261
262 // close service handle
263 CloseServiceHandle(schs);
264 end;
265
266 // close service control
267 // manager handle
268 CloseServiceHandle(schm);
269 end;
270
271 // return TRUE if
272 // the service status is stopped
273 Result :=
274 SERVICE_STOPPED =
275 ss.dwCurrentState;
276 end;
277
278 //Example usage:
279
280 if (ServiceStart('\\ComputerName', 'alerter')) then
281 begin
282 // "alerter" service on \\ComputerName
283 // was started
284 // take appropriate action here
285 end;
286
287 // stop "alerter" service
288 // running on the local
289 // computer
290 if (ServiceStop('', 'alerter')) then
291 begin
292 end;
|