我们进行Windows编程的时候,经常涉及到Windows服务编程,针对Windows服务我们该怎么编程呢,
我们先来实现一个Windows服务并实现之,请见注释代码分析。
1. /* 头文件 */
2. #include <windows.h>
3. /* 全局变量 */
4. SERVICE_STATUS SplSrvServiceStatus;
5. SERVICE_STATUS_HANDLE SplSrvServiceStatusHandle;
6. /* 函数声明 */
7. VOID SvcDebugOut(LPSTR String, DWORD Status);
8. VOID WINAPI SplSrvServiceCtrlHandler (DWORD opcode);
9. VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv);
10. DWORD SplSrvServiceInitialization (DWORD argc, LPTSTR *argv,
11. DWORD *specificError);
12.
13. /*************************************
14. * VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv)
15. * 功能 服务启动函数
16. *
17. * 参数 未使用
18. **************************************/
19. VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv)
20. {
21. DWORD status;
22. DWORD specificError;
23. // 填充SERVICE_STATUS 结构
24. SplSrvServiceStatus.dwServiceType = SERVICE_WIN32;
25. SplSrvServiceStatus.dwCurrentState
26. // 服务在运行
27. SplSrvServiceStatus.dwControlsAccepted
28. = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
29. SplSrvServiceStatus.dwWin32ExitCode = 0;
30. SplSrvServiceStatus.dwServiceSpecificExitCode = 0;
31. SplSrvServiceStatus.dwCheckPoint = 0;
32. SplSrvServiceStatus.dwWaitHint = 0;
33. // 注册服务控制请求处理例程
34. SplSrvServiceStatusHandle = RegisterServiceCtrlHandler(
35. "Sample_Srv", // 服务名,在创建服务时使用了
36. // SERVICE_WIN32_OWN_PROCESS,因此本参数被忽略。
37. // 控制请求处理例程,函数名
38.
39. if (SplSrvServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
40. {
41. " [SPLSRV_SERVICE] RegisterServiceCtrlHandler "
42. "failed %d\n", GetLastError());
43. return;
44. }
45. // 初始化工作,本示例未使用,函数为空
46. status = SplSrvServiceInitialization(argc,argv, &specificError);
47. // 初始化出错,用户自行修改
48. if (status != NO_ERROR)
49. {
50. SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;
51. SplSrvServiceStatus.dwCheckPoint = 0;
52. SplSrvServiceStatus.dwWaitHint = 0;
53. SplSrvServiceStatus.dwWin32ExitCode = status;
54. SplSrvServiceStatus.dwServiceSpecificExitCode = specificError;
55.
56. SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus);
57. return;
58. }
59. // 初始化完成,设置运行状态
60. SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;
61. SplSrvServiceStatus.dwCheckPoint = 0;
62. SplSrvServiceStatus.dwWaitHint = 0;
63.
64. if (!SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus))
65. {
66. status = GetLastError();
67. " [SPLSRV_SERVICE] SetServiceStatus error %ld\n",status);
68. }
69. // 用户自行修改,用于完成服务的工作
70. " [SPLSRV_SERVICE] Returning the Main Thread \n",0);
71.
72. return;
73. }
74.
75.
76. /*************************************
77. * DWORD SplSrvServiceInitialization(DWORD argc,
78. * LPTSTR *argv,
79. * DWORD *specificError)
80. * 功能 初始化,这里未进行任何工作,留待读者修改
81. *
82. * 参数
83. **************************************/
84. DWORD SplSrvServiceInitialization(DWORD argc,
85. LPTSTR *argv,
86. DWORD *specificError)
87. {
88. return(0);
89. }
90.
91. /*************************************
92. * VOID WINAPI SplSrvServiceCtrlHandler (DWORD Opcode)
93. * 功能 服务控制请求的处理函数,与ControlService函数配合。
94. *
95. * 参数 服务控制码
96. **************************************/
97. VOID WINAPI SplSrvServiceCtrlHandler (DWORD Opcode)
98. {
99. DWORD status;
100. switch(Opcode)
101. {
102. case SERVICE_CONTROL_PAUSE:
103. // 完成相关功能
104. SplSrvServiceStatus.dwCurrentState = SERVICE_PAUSED;
105. break;
106. case SERVICE_CONTROL_CONTINUE:
107. // 完成相关功能
108. SplSrvServiceStatus.dwCurrentState = SERVICE_RUNNING;
109. break;
110. case SERVICE_CONTROL_STOP:
111. // 完成相关功能
112. SplSrvServiceStatus.dwWin32ExitCode = 0;
113. SplSrvServiceStatus.dwCurrentState = SERVICE_STOPPED;
114. SplSrvServiceStatus.dwCheckPoint = 0;
115. SplSrvServiceStatus.dwWaitHint = 0;
116.
117. if (!SetServiceStatus (SplSrvServiceStatusHandle,
118. &SplSrvServiceStatus))
119. {
120. status = GetLastError();
121. " [SPLSRV_SERVICE] SetServiceStatus error %ld\n",
122. status);
123. }
124. " [SPLSRV_SERVICE] Leaving SplSrvService \n",0);
125. return;
126. case SERVICE_CONTROL_INTERROGATE:
127. // 收到此请求后发出声响,演示服务控制请求的处理过程,读者可自行修改
128. MessageBeep(MB_OK);
129. break;
130. default:
131. " [SPLSRV_SERVICE] Unrecognized opcode %ld\n",
132. Opcode);
133. }
134. // 当前状态
135. if (!SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus))
136. {
137. status = GetLastError();
138. " [SPLSRV_SERVICE] SetServiceStatus error %ld\n",
139. status);
140. }
141. return;
142. }
143. /*************************************
144. * void main( )
145. * 功能 程序入口函数,注册服务启动函数等。
146. *
147. * 参数 服务控制码
148. **************************************/
149. void main( )
150. {
151. // 设置SERVICE_TABLE_ENTRY 数据结构,以NULL 结构结束,
152. // 作为StartServiceCtrlDispatcher 函数的参数。
153. SERVICE_TABLE_ENTRY DispatchTable[] =
154. {
155. "Sample_Srv", (LPSERVICE_MAIN_FUNCTION) SplSrvServiceStart },
156. { NULL, NULL }
157. };
158. if (!StartServiceCtrlDispatcher( DispatchTable))
159. {
160. " [SPLSRV_SERVICE] StartServiceCtrlDispatcher (%d)\n",
161. GetLastError());
162. }
163. }
164. /*************************************
165. * VOID SvcDebugOut(LPSTR String, DWORD Status)
166. * 功能 显示信息给调试器。
167. *
168. * 参数 LPSTR String 消息字符串
169. * DWORD Status 状态
170. **************************************/
171. VOID SvcDebugOut(LPSTR String, DWORD Status)
172. {
173. CHAR Buffer[1024];
174. if (strlen(String) < 1000)
175. {
176. wsprintf(Buffer, String, Status);
177. OutputDebugString(Buffer);
178. }
179. }
然后我们实现了服务以后,需要进行安装,删除服务
具体实现代码如下,请见代码分析
1. **************************************/
2. /* 头文件 */
3. #include <windows.h>
4. #include <tchar.h>
5. #include <stdio.h>
6. /* 全局变量 */
7. SC_HANDLE schService;
8. SC_HANDLE schSCManager;
9. LPTSTR szServiceName = TEXT("Sample_Srv");
10.
11. /*************************************
12. * BOOL CreateSampleService(LPTSTR szPath, LPSTR szServiceName)
13. * 功能 创建服务
14. *
15. * 参数
16. * SC_HANDLE schSCManager,SCM句柄
17. * LPTSTR szPath, 服务程序的路径
18. * LPSTR szServiceName, 服务名
19. **************************************/
20. BOOL CreateSampleService(
21. SC_HANDLE schSCManager,
22. LPTSTR szPath,
23. LPSTR szServiceName)
24. {
25. // 创建服务
26. schService = CreateService(
27. // SCM 句柄
28. // 服务名
29. "Service sample", // 显示的服务名
30. // 存取权限
31. // 服务类别
32. // 启动类别
33. // 错误控制类别
34. // 服务的可执行文件路径
35. // no load ordering group
36. // no tag identifier
37. // no dependencies
38. // LocalSystem account
39. // no password
40.
41. if (schService == NULL)
42. {
43. "CreateService failed (%d)\n", GetLastError());
44. return FALSE;
45. }
46. else
47. {
48. "CreateService succeeded\n");
49. CloseServiceHandle(schService);
50. return TRUE;
51. }
52. }
53.
54. /*************************************
55. * BOOL DeleteSampleService(LPTSTR szNameOfService)
56. * 功能 删除服务
57. *
58. * 参数 LPTSTR szNameOfService 服务的名字
59. **************************************/
60. BOOL DeleteSampleService(LPTSTR szNameOfService)
61. {
62. schService = OpenService(
63. // SCM 句柄
64. // 服务名
65. // 可删除
66.
67. if (schService == NULL)
68. {
69. "OpenService failed (%d)\n", GetLastError());
70. return FALSE;
71. }
72. // 删除服务
73. if (! DeleteService(schService) )
74. {
75. "DeleteService failed (%d)\n", GetLastError());
76. return FALSE;
77. }
78. else
79. "DeleteService succeeded\n");
80. // 关闭句柄
81. CloseServiceHandle(schService);
82. return TRUE;
83. }
84. /*************************************
85. * void main( int argc, TCHAR *argv[] )
86. * 功能 演示
87. *
88. * 参数 未使用
89. **************************************/
90. void main( int argc, TCHAR *argv[] )
91. {
92. TCHAR szBinFilePath[MAX_PATH];
93. PTCHAR pTemp;
94. DWORD dwStopError;
95. // 构造服务可执行程序的路径
96. GetModuleFileName(NULL,szBinFilePath,MAX_PATH);
97. pTemp = szBinFilePath+lstrlen(szBinFilePath);
98. while(*--pTemp!='\\');
99. "\\SplSrv.exe"));
100.
101. // 打开 SCM
102. schSCManager = OpenSCManager(
103. // local machine
104. // ServicesActive database
105. // full access rights
106.
107. if (NULL == schSCManager)
108. "OpenSCManager failed (%d)\n", GetLastError());
109.
110. // 创建服务
111. CreateSampleService(schSCManager, szBinFilePath, szServiceName);
112. // 启动服务
113. StartSampleService(schSCManager,szServiceName);
114. // 发送请求控制
115. ControlSampleService(SERVICE_CONTROL_INTERROGATE);
116. ControlSampleService(SERVICE_CONTROL_CONTINUE);
117. // 停止服务
118. dwStopError = StopService( schSCManager, szServiceName,
119. TRUE, 1000);
120.
121. if(ERROR_SUCCESS == dwStopError)
122. {
123. "Service Stoped\n");
124. }
125. else
126. {
127. "Service stoped error (%u)\n",dwStopError);
128. }
129. // 删除服务
130. DeleteSampleService(szServiceName);
131. CloseServiceHandle(schSCManager);
132. }
然后我们如何控制服务呢,我们来实现启动、停止服务,向服务发送请求。
1. /* 头文件 */
2. #include <windows.h>
3. #include <tchar.h>
4. #include <stdio.h>
5. /* 全局变量 */
6. extern SC_HANDLE schService; // 在init.c中定义,下同
7. extern SC_HANDLE schSCManager;
8. extern LPTSTR szServiceName;
9.
10. /*************************************
11. * BOOL StartSampleService(SC_HANDLE schSCManager,LPTSTR szServiceName)
12. * 功能 启动服务
13. *
14. * 参数 SC_HANDLE schSCManager SCM 句柄
15. * LPTSTR szServiceName 服务名
16. **************************************/
17. BOOL StartSampleService(SC_HANDLE schSCManager,LPTSTR szServiceName)
18. {
19. SC_HANDLE schService;
20. SERVICE_STATUS_PROCESS ssStatus;
21. DWORD dwOldCheckPoint;
22. DWORD dwStartTickCount;
23. DWORD dwWaitTime;
24. DWORD dwBytesNeeded;
25. // 打开服务
26. schService = OpenService(
27. // SCM database
28. // service name
29. SERVICE_ALL_ACCESS);
30. if (schService == NULL)
31. {
32. return 0;
33. }
34. // 启动服务
35. if (!StartService(
36. // handle to service
37. // number of arguments
38. // no arguments
39. {
40. "Service start error (%u).\n",GetLastError());
41. return 0;
42. }
43. else
44. {
45. "Service start pending.\n");
46. }
47.
48. // 验证状态
49. if (!QueryServiceStatusEx(
50. // handle to service
51. // info level
52. LPBYTE)&ssStatus, // address of structure
53. sizeof(SERVICE_STATUS_PROCESS), // size of structure
54. // if buffer too small
55. {
56. return 0;
57. }
58.
59. // tick count & checkpoint.
60. dwStartTickCount = GetTickCount();
61. dwOldCheckPoint = ssStatus.dwCheckPoint;
62. // 查询状态,确定 PENDING 状态结束
63. while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
64. {
65. // 等待一段时间
66. dwWaitTime = ssStatus.dwWaitHint / 10;
67. if( dwWaitTime < 1000 )
68. dwWaitTime = 1000;
69. else if ( dwWaitTime > 10000 )
70. dwWaitTime = 10000;
71. Sleep( dwWaitTime );
72. // 再次查询
73. if (!QueryServiceStatusEx(
74. // handle to service
75. // info level
76. LPBYTE)&ssStatus, // address of structure
77. sizeof(SERVICE_STATUS_PROCESS), // size of structure
78. // if buffer too small
79. break;
80. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
81. {
82. // 进程创建中
83. dwStartTickCount = GetTickCount();
84. dwOldCheckPoint = ssStatus.dwCheckPoint;
85. }
86. else
87. {
88. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
89. {
90. // WaitHint 时间到
91. break;
92. }
93. }
94. }
95. // 关闭句柄
96. CloseServiceHandle(schService);
97. // 判断是否创建成功(状态由PENDING变为RUNNING)
98. if (ssStatus.dwCurrentState == SERVICE_RUNNING)
99. {
100. "StartService SUCCESS.\n");
101. return 1;
102. }
103. else
104. {
105. "\nService not started. \n");
106. " Current State: %d\n", ssStatus.dwCurrentState);
107. " Exit Code: %d\n", ssStatus.dwWin32ExitCode);
108. " Service Specific Exit Code: %d\n",
109. ssStatus.dwServiceSpecificExitCode);
110. " Check Point: %d\n", ssStatus.dwCheckPoint);
111. " Wait Hint: %d\n", ssStatus.dwWaitHint);
112. return 0;
113. }
114. }
115.
116. /*************************************
117. * DWORD StopService( SC_HANDLE hSCM,
118. LPTSTR szServiceName,
119. BOOL fStopDependencies,
120. DWORD dwTimeout )
121. * 功能 停止服务
122. *
123. * 参数 SC_HANDLE hSCM SCM 句柄
124. * LPTSTR szServiceName 服务名
125. * BOOL fStopDependencies 是否结束依赖的服务
126. * DWORD dwTimeout 超时
127. **************************************/
128. DWORD StopService(SC_HANDLE hSCM,
129. LPTSTR szServiceName,
130. BOOL fStopDependencies,
131. DWORD dwTimeout )
132. {
133. SERVICE_STATUS_PROCESS ssp;
134. SERVICE_STATUS ss;
135. DWORD dwStartTime = GetTickCount();
136. DWORD dwBytesNeeded;
137. // 打开服务
138. SC_HANDLE hService = OpenService(
139. // SCM 句柄
140. // 服务名
141. SERVICE_ALL_ACCESS);
142.
143. // 查询状态,确定是否已经停止
144. if ( !QueryServiceStatusEx(
145. hService,
146. SC_STATUS_PROCESS_INFO,
147. LPBYTE)&ssp,
148. sizeof(SERVICE_STATUS_PROCESS),
149. &dwBytesNeeded ) )
150. {
151. return GetLastError();
152. }
153. if ( ssp.dwCurrentState == SERVICE_STOPPED )
154. {
155. return ERROR_SUCCESS;
156. }
157. // 如果是 STOP_PENDING 状态,则只需等待
158. while ( ssp.dwCurrentState == SERVICE_STOP_PENDING )
159. {
160. Sleep( ssp.dwWaitHint );
161. // 循环查询,直到状态改变
162. if ( !QueryServiceStatusEx(
163. hService,
164. SC_STATUS_PROCESS_INFO,
165. LPBYTE)&ssp,
166. sizeof(SERVICE_STATUS_PROCESS),
167. &dwBytesNeeded ) )
168. {
169. return GetLastError();
170. }
171. if ( ssp.dwCurrentState == SERVICE_STOPPED )
172. {
173. return ERROR_SUCCESS;
174. }
175. if ( GetTickCount() - dwStartTime > dwTimeout )
176. {
177. return ERROR_TIMEOUT;
178. }
179. }
180.
181. // 先结束依赖服务
182. if ( fStopDependencies )
183. {
184. DWORD i;
185. DWORD dwBytesNeeded;
186. DWORD dwCount;
187.
188. LPENUM_SERVICE_STATUS lpDependencies = NULL;
189. ENUM_SERVICE_STATUS ess;
190. SC_HANDLE hDepService;
191.
192. // 使用 0 大小的 buf,获取buf的大小
193. // 如果 EnumDependentServices 直接返回成功,说明没有依赖服务
194. if ( !EnumDependentServices( hService, SERVICE_ACTIVE,
195. lpDependencies, 0, &dwBytesNeeded, &dwCount ) )
196. {
197. if ( GetLastError() != ERROR_MORE_DATA )
198. return GetLastError(); // Unexpected error
199.
200. // 分配缓冲区存储依赖服务的数据
201. lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(
202. GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );
203.
204. if ( !lpDependencies )
205. return GetLastError();
206.
207. __try {
208. // 获得依赖服务
209. if ( !EnumDependentServices( hService, SERVICE_ACTIVE,
210. lpDependencies, dwBytesNeeded, &dwBytesNeeded,
211. &dwCount ) )
212. return GetLastError();
213.
214. for ( i = 0; i < dwCount; i++ )
215. {
216. ess = *(lpDependencies + i);
217.
218. // 打开服务
219. hDepService = OpenService( hSCM, ess.lpServiceName,
220. SERVICE_STOP | SERVICE_QUERY_STATUS );
221. if ( !hDepService )
222. return GetLastError();
223.
224. __try {
225. // 结束服务
226. if ( !ControlService( hDepService,
227. SERVICE_CONTROL_STOP,
228. &ss ) )
229. return GetLastError();
230.
231. // 等待服务结束
232. while ( ss.dwCurrentState != SERVICE_STOPPED )
233. {
234. Sleep( ss.dwWaitHint );
235. if ( !QueryServiceStatusEx(
236. hDepService,
237. SC_STATUS_PROCESS_INFO,
238. LPBYTE)&ssp,
239. sizeof(SERVICE_STATUS_PROCESS),
240. &dwBytesNeeded ) )
241. return GetLastError();
242.
243. if ( ss.dwCurrentState == SERVICE_STOPPED )
244. break;
245.
246. if ( GetTickCount() - dwStartTime > dwTimeout )
247. return ERROR_TIMEOUT;
248. }
249.
250. }
251. __finally
252. {
253. // 关闭服务
254. CloseServiceHandle( hDepService );
255.
256. }
257. }
258. }
259. __finally
260. {
261. // 释放内存
262. HeapFree( GetProcessHeap(), 0, lpDependencies );
263. }
264. }
265. }
266.
267. // 所有的依赖服务已经结束,结束指定服务
268. if ( !ControlService( hService, SERVICE_CONTROL_STOP, &ss ) )
269. return GetLastError();
270. while ( ss.dwCurrentState != SERVICE_STOPPED )
271. {
272. Sleep( ss.dwWaitHint );
273. if ( !QueryServiceStatusEx(
274. hService,
275. SC_STATUS_PROCESS_INFO,
276. LPBYTE)&ssp,
277. sizeof(SERVICE_STATUS_PROCESS),
278. &dwBytesNeeded ) )
279. return GetLastError();
280.
281. if ( ss.dwCurrentState == SERVICE_STOPPED )
282. break;
283.
284. if ( GetTickCount() - dwStartTime > dwTimeout )
285. return ERROR_TIMEOUT;
286. }
287. return ERROR_SUCCESS;
288. }
289.
290. /*************************************
291. * BOOL ControlSampleService(DWORD fdwControl)
292. * 功能 向服务发送控制码
293. *
294. * 参数 DWORD fdwControl 控制码值
295. * SCM 句柄,服务名直接使用全局变量
296. **************************************/
297. BOOL ControlSampleService(DWORD fdwControl)
298. {
299. SERVICE_STATUS ssStatus;
300. DWORD fdwAccess;
301. DWORD dwStartTickCount, dwWaitTime;
302.
303. // Access
304. switch (fdwControl)
305. {
306. case SERVICE_CONTROL_STOP:
307. fdwAccess = SERVICE_STOP;
308. break;
309. case SERVICE_CONTROL_PAUSE:
310. case SERVICE_CONTROL_CONTINUE:
311. fdwAccess = SERVICE_PAUSE_CONTINUE;
312. break;
313. case SERVICE_CONTROL_INTERROGATE:
314. fdwAccess = SERVICE_INTERROGATE;
315. break;
316. default:
317. fdwAccess = SERVICE_INTERROGATE;
318. }
319.
320. // 打开服务
321. schService = OpenService(
322. // SCManager 句柄
323. // 服务名
324. // 存取权限
325. if (schService == NULL)
326. {
327. "OpenService failed (%d)\n", GetLastError());
328. return FALSE;
329. }
330.
331. // 发送控制码
332. if (! ControlService(
333. // 服务的句柄
334. // 控制码
335. // 状态
336. {
337. "ControlService failed (%d)\n", GetLastError());
338. return FALSE;
339. }
340.
341. // 显示状态
342. "\nStatus of Sample_Srv: \n");
343. " Service Type: 0x%x\n", ssStatus.dwServiceType);
344. " Current State: 0x%x\n", ssStatus.dwCurrentState);
345. " Controls Accepted: 0x%x\n",
346. ssStatus.dwControlsAccepted);
347. " Exit Code: %d\n", ssStatus.dwWin32ExitCode);
348. " Service Specific Exit Code: %d\n",
349. ssStatus.dwServiceSpecificExitCode);
350. " Check Point: %d\n", ssStatus.dwCheckPoint);
351. " Wait Hint: %d\n", ssStatus.dwWaitHint);
352.
353. return TRUE;
354. }
标签:服务,SERVICE,Windows,DWORD,ssStatus,return,SplSrvServiceStatus,安装
From: https://blog.51cto.com/u_130277/6457474