首页 > 系统相关 >实现Windows服务并安装,控制

实现Windows服务并安装,控制

时间:2023-06-11 13:02:49浏览次数:40  
标签:服务 SERVICE Windows DWORD ssStatus return SplSrvServiceStatus 安装


我们进行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

相关文章

  • java——微服务——spring cloud——Nacos——Nacos服务分级存储模型——集群配置
                  ......
  • 在 Windows 上运行 Podman: 操作指南
    在Windows上运行Podman:操作指南 在Windows上运行Podman:操作指南https://www.redhat.com/sysadmin/run-podman-windows2021年9月的时候,我写过一篇关于如何在Windows上运行Podman的文章。在那篇文章中,我讨论了为什么你必须设置WSL(WindowsSubsystemfor......
  • Gradle 的安装与配置 + eclipse 里安装 Gradle 插件
    一、什么是Gradle基于ApacheAnt和ApacheMaven概念的项目自动化构建开源工具,基于Groovy这个特定DSL语言来进行声明项目设置,也增加了基于Kotlin语言的kotlin-basedDSL。简介:Gradle是一个基于JVM的构建工具,是一款通用灵活的构建工具,支持maven,Ivy仓库,支持传递性依赖管理,而不需要远......
  • Linux服务器配置SSH免密码登录后,登录仍提示输入密码(一次真实的问题排查解决记录)
    我们知道两台Linux服务器机器之间如果使用ssh命令登录或scp/rsync命令传输文件每一次都需要输入用户名相对应的密码,如果要免密码,则需要对两台Linux服务器机器之间进行SSH互信。一.SSH介绍1.SSH互信原理虽然这是废话,也希望大家了解一下。SSH(SecureShell)是一种安全的传输协议,它可以......
  • 1.安装系统
    每个网卡都有自己的MAC地址,MAC是厂家烧在网卡上的机器之间的通信是通过MAC来发送的,形式是广播,每个人都能收到,只是检测到目标MC不是自己的MAC就把消息丢弃使用网关进行MAC访问上述形式太吵闹,类似大厅吃饭,我们需要局域交流,所以才有IP地址交流(局域网-包间)ip中的子网划分依靠的是......
  • 《CentOS系统管理与服务器配置》pdf电子书免费下载
    本书是职业教育“十三五”改革创新规划教材,依据高职高专网络技术专业人才培养方案的要求,并参照相关的国家职业技能标准编写而成。本书以基于RedHat Linux 提供的可自由使用源代码的企业级Linux发行版本CentOS 6操作系统为平台,选取面向工作岗位的项目案例,采用项目导向、任务驱......
  • 在Windows上无docker直接将基于Solon的jar包通过IDEA部署到Linux的docker上
    为何会选择学习solon?springboot对于我开发小企业应用太重,启动太慢,下班太晚!为何都用windows,还想着不安装dockerdesktop洁癖,运行路径能短就短。步骤(以solon官网的helloword为例)1、下载helloworld代码传送阵:点击我2、通过IDEA打开代码,并运行它(我是下载基于maven版本的)。3......
  • 针对SpringBoot服务端返回的空对象和空数组问题
    返回的Json会自动过滤掉空指针的对象,但是若遇到非空指针的没有任何内容的对象,举例如下:publicclassPerson{privateStringname;privateIntegerage;privateBooleansex;publicStringgetName(){returnname;}publicvoidsetNam......
  • gltlab安装部署小计
    镜像源:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ee/yum/el7/数据目录文件迁移参考:https://blog.csdn.net/qq_50247813/article/details/126250101安装epel和gityum-yinstallepel-releasegit安装依赖yum-yinstallcurlopenssh-serveropenssh-clientspostfixcroniew......
  • Linux系统下配置Nginx服务器
    Nginx是一个高性能的开源HTTP和反向代理服务器,也可以作为电子邮件(SMTP/POP3/IMAP)代理服务器、负载均衡器和HTTP缓存服务器,使用在安装Nginx之前,需要安装一些其他软件依赖,如gcc、pcre、zlib和openssl。1、yum installgcc-ygcc是GNUCompilerCollection的简称,包含编译器和其他编......