【发布时间】:2017-12-13 15:56:59
【问题描述】:
我有一个 C++ 编写的 Windows 服务,在启动时,如果 SERVICE_STATUS 在 SERVICE_START_PENDING 中停留的时间过长,我最终会出现此错误:
Error 1053: The service did not respond to the start or control request in a timely fashion
当进度条对话框保持打开状态时会发生这种情况。它不会影响服务启动本身。服务会在SERVICE_START_PENDING继续,直到工作完成,我设置SERVICE_RUNNING。
dwWaitHint 上的 Windows 文档在这里:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
声明服务必须在 dwWaitHint 时间过去之前以递增的 dwCheckPoint 调用 SetServiceStatus。
例如,我将 dwWaitHint 设置为 5 分钟,并每隔 10 秒调用一次 SetServiceStatus,并增加 dwCheckPoint,但 5 分钟后我仍然收到 1053 错误。换句话说,SetServiceStatus 调用似乎没有做任何事情。 (我检查了这些电话并没有失败)。
通过上述操作,服务启动时间不能比dwWaitHint更长吗???
更新:我可以使用 Microsoft 的服务示例代码进行重现。这是一个sn-p。
{
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
// Report initial status to the SCM
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 300000 );
int limit = 6; // 6 minutes total
while(limit--)
{
Sleep(60000); // sleep 1 min
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 300000 ); // 5 minute dwWaitHint
}
// We've completed startup, report RUNNING to SCM
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
}
VOID ReportSvcStatus( DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ( (dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED) )
gSvcStatus.dwCheckPoint = 0;
else gSvcStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the SCM.
SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}
【问题讨论】:
-
请出示您的实际代码。我已经编写了几个服务,
SetServiceStatus()按文档说明工作,因此您实际上可能没有正确使用它。不要描述你的代码,展示它。 -
我刚刚添加了一些代码。我可以用微软的示例服务代码重现。我将 dwWaitHint 设置为 5 分钟(每次调用 SetServiceStatus 时),但我总共工作了 6 分钟。 (1 分钟 x 6,每次在迭代之间调用 SetServiceStatus)。 5 分钟后我收到超时错误,即使服务一直运行到完成。也许解决方案是每次调用 SetServiceStatus 时增加 dwWaitHint
-
一开始 - 为什么不简化代码呢?对于 2 用
SERVICE_START_PENDING调用ReportSvcStatus而不是这个:do { ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 4000 ); Sleep(2000); } while(--limit);i 进行测试的时间间隔相对较小 - 4 秒等待提示并每 2 秒更新一次状态。而是固定条件while(--limit)甚至更好地用于测试集,例如while (!IsDebuggerPresent());在我的测试中所有正确的与services.exe 一起使用。Error 1053:仅显示 gui shell - mmc.exe 中的服务管理单元。 -
但这只是这个实用程序的糟糕设计,并不重要。重要的是services.exe对此有何反应