当前位置:   article > 正文

C++调用StartService启动服务失败1053分析与解决_startservice 1053

startservice 1053

网上通用的OpenSCManager->OpenService->StartService这种启动方式是正确的,但是很多人遇到开启服务时出现1053错误,下面来分析与解决

官网对于StartServiceW的描述(我程序里用的宽字符版本)

https://docs.microsoft.com/zh-cn/windows/win32/api/winsvc/nf-winsvc-startservicew

一开始GetLastERROR错误1053,百度解决方案大致就”注册表修改超时、开启桌面交互“这两种,但是依旧不行

各种骚操作都没有解决,直到我看到官方文档对返回值的描述

ERROR_SERVICE_REQUEST_TIMEOUT

The process for the service was started, but it did not call StartServiceCtrlDispatcher, or the thread that called StartServiceCtrlDispatcher may be blocked in a control handler function.

翻译一下:

错误\服务\请求\超时
服务的进程已启动,但它没有调用StartServiceCtrlDispatcher,或者在控制处理程序函数中可能阻止调用StartServiceCtrlDispatcher的线程。

原理这个错误的超时不仅包含启动超时,也包含线程启动后没有给管理器报告状态的超时

现在跳转到StartServiceCtrlDispatcherA的官方文档,查看它的例子

https://docs.microsoft.com/zh-cn/windows/win32/api/winsvc/nf-winsvc-startservicectrldispatchera

For an example, see Writing a Service Program's Main Function.

请结合例子描述里的另一个例子继续研究

https://docs.microsoft.com/zh-cn/windows/win32/services/svc-cpp

现在总结一下大致是这个逻辑

也就是说需要服务程序主动调用StartServiceCtrlDispatcher向管理器发送启动成功的状态,管理器才认为启动成功

所以要在运行的exe内进行”上报状态“操作才行

根据官方文档整理的服务程序代码例子,修改了注释(注册服务请自行百度解决或看官方源码),运行这个程序会在当前路径下生成SERVICE666.txt,在SvcMain函数最后都添加自己的代码,SvcInit函数是一个例子

  1. #include <windows.h>
  2. #include <tchar.h>
  3. #include <strsafe.h>
  4. //#include "sample.h"
  5. #pragma comment(lib, "advapi32.lib")
  6. #pragma warning(disable:4996)
  7. #define SVCNAME TEXT("AAA-SvcName")
  8. #define SVC_ERROR ((DWORD)0xC0020001L)
  9. SERVICE_STATUS gSvcStatus;
  10. SERVICE_STATUS_HANDLE gSvcStatusHandle;
  11. HANDLE ghSvcStopEvent = NULL;
  12. VOID WINAPI SvcCtrlHandler(DWORD);
  13. VOID WINAPI SvcMain(DWORD, LPTSTR *);
  14. VOID ReportSvcStatus(DWORD, DWORD, DWORD);
  15. VOID SvcInit(DWORD, LPTSTR *);
  16. VOID SvcReportEvent(LPTSTR);
  17. void __cdecl _tmain(int argc, TCHAR *argv[])
  18. {
  19. // TO_DO: Add any additional services for the process to this table.
  20. SERVICE_TABLE_ENTRY DispatchTable[] =
  21. {
  22. { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
  23. { NULL, NULL }
  24. };
  25. // This call returns when the service has stopped.
  26. // The process should simply terminate when the call returns.
  27. if (!StartServiceCtrlDispatcher(DispatchTable))
  28. {
  29. SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
  30. }
  31. }
  32. //服务执行入口
  33. VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
  34. {
  35. // Register the handler function for the service
  36. gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME,SvcCtrlHandler);
  37. if (!gSvcStatusHandle)
  38. {
  39. SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
  40. return;
  41. }
  42. // These SERVICE_STATUS members remain as set here
  43. gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  44. gSvcStatus.dwServiceSpecificExitCode = 0;
  45. // Report initial status to the SCM
  46. ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
  47. // Perform service-specific initialization and work.
  48. SvcInit(dwArgc, lpszArgv);
  49. }
  50. //服务代码
  51. VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv)
  52. {
  53. // TO_DO: Declare and set any required variables.
  54. // Be sure to periodically call ReportSvcStatus() with
  55. // SERVICE_START_PENDING. If initialization fails, call
  56. // ReportSvcStatus with SERVICE_STOPPED.
  57. // Create an event. The control handler function, SvcCtrlHandler,
  58. // signals this event when it receives the stop control code.
  59. ghSvcStopEvent = CreateEvent(
  60. NULL, // default security attributes
  61. TRUE, // manual reset event
  62. FALSE, // not signaled
  63. NULL); // no name
  64. if (ghSvcStopEvent == NULL)
  65. {
  66. ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
  67. return;
  68. }
  69. // Report running status when initialization is complete.
  70. ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
  71. //
  72. wchar_t szFilePath[MAX_PATH + 1] = { 0 };
  73. GetModuleFileNameW(NULL, szFilePath, MAX_PATH);
  74. (wcsrchr(szFilePath, '\\'))[1] = 0; // 删除文件名,只获得路径字串
  75. wcscat(szFilePath, L"SERVICE666.txt");
  76. FILE *file = _wfopen(szFilePath, L"wb");
  77. wchar_t *ptxt = L"SERVICE666:SERVICE_RUNNING";
  78. fwrite(ptxt, sizeof(wchar_t), wcslen(ptxt), file);
  79. fclose(file);
  80. //
  81. // TO_DO: Perform work until service stops.
  82. while (1)
  83. {
  84. // Check whether to stop the service.
  85. WaitForSingleObject(ghSvcStopEvent, INFINITE);
  86. ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
  87. return;
  88. }
  89. }
  90. //向管理器报告服务状态
  91. VOID ReportSvcStatus(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint)
  92. {
  93. static DWORD dwCheckPoint = 1;
  94. // Fill in the SERVICE_STATUS structure.
  95. gSvcStatus.dwCurrentState = dwCurrentState;
  96. gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
  97. gSvcStatus.dwWaitHint = dwWaitHint;
  98. if (dwCurrentState == SERVICE_START_PENDING)
  99. gSvcStatus.dwControlsAccepted = 0;
  100. else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  101. if ((dwCurrentState == SERVICE_RUNNING) ||
  102. (dwCurrentState == SERVICE_STOPPED))
  103. gSvcStatus.dwCheckPoint = 0;
  104. else gSvcStatus.dwCheckPoint = dwCheckPoint++;
  105. // Report the status of the service to the SCM.
  106. SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
  107. }
  108. //每当使用controlService函数向服务发送控制代码时,由SCM调用
  109. VOID WINAPI SvcCtrlHandler(DWORD dwCtrl)
  110. {
  111. // Handle the requested control code.
  112. switch (dwCtrl)
  113. {
  114. case SERVICE_CONTROL_STOP:
  115. ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
  116. // Signal the service to stop.
  117. SetEvent(ghSvcStopEvent);
  118. ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
  119. return;
  120. case SERVICE_CONTROL_INTERROGATE:
  121. break;
  122. default:
  123. break;
  124. }
  125. }
  126. //将消息记录到事件日志
  127. VOID SvcReportEvent(LPTSTR szFunction)
  128. {
  129. HANDLE hEventSource;
  130. LPCTSTR lpszStrings[2];
  131. TCHAR Buffer[80];
  132. hEventSource = RegisterEventSource(NULL, SVCNAME);
  133. if (NULL != hEventSource)
  134. {
  135. StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());
  136. lpszStrings[0] = SVCNAME;
  137. lpszStrings[1] = Buffer;
  138. ReportEvent(hEventSource, // event log handle
  139. EVENTLOG_ERROR_TYPE, // event type
  140. 0, // event category
  141. SVC_ERROR, // event identifier
  142. NULL, // no security identifier
  143. 2, // size of lpszStrings array
  144. 0, // no binary data
  145. lpszStrings, // array of strings
  146. NULL); // no binary data
  147. DeregisterEventSource(hEventSource);
  148. }
  149. }

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号