StartService() 立即 returns 和 ERROR_SERVICE_REQUEST_TIMEOUT
StartService() immediately returns with ERROR_SERVICE_REQUEST_TIMEOUT
我创建了一个 windows 服务,我安装了它:
SC_HANDLE service = CreateServiceA
(
scm,
"turboledz",
"TurboLEDz",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
servicepath,
NULL,
NULL,
NULL,
NULL,
NULL
);
这就成功了。
然后我可以查询它的状态,使用 QueryServiceStatus(service, &servstat);
可以预见 returns SERVICE_STOPPED.
到目前为止,还不错。
当我随后启动服务时,要么以编程方式使用:
const int started = StartServiceA
(
service,
0, // num service arguments.
NULL
);
if (started)
{
LOGI("turboledz service has been started.");
}
else
{
const DWORD err = GetLastError();
LOGI("Failed to start service. Error: 0x%lx", err);
return 5;
}
...或使用 sc
命令行工具:
sc start turboledz
然后我立即(在几分之一秒内)提示错误:
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
对应ERROR_SERVICE_REQUEST_TIMEOUT.
此外,由于我的服务做的第一件事是创建一个日志文件,而这个日志文件不存在,我必须得出结论,SCM 甚至没有尝试启动我的服务。
顺便说一下,该服务有一个正确设置的 binpath,所以这不是问题。
这引发了很多问题:
- TIMEOUT 怎么会瞬间失败?
- 为什么SCM没有启动服务进程?
注意:我在创建和启动服务时拥有管理员权限。
注意:这不是缺少服务可执行文件的问题,因为如果我删除它,sc 错误会变为 ERROR_SERVICE_DOES_NOT_EXIST
更新
事件查看器显示 SCM 日志,其中包含一个彻头彻尾的谎言:从服务启动到超时错误之间从未经过 30,000 毫秒。
创建、启动、超时,都发生在12:52:43。
更新 2
main() 代码:
...
SERVICE_TABLE_ENTRY servtabl[] =
{
{L"turboledz", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};
const int startres = StartServiceCtrlDispatcher( servtabl );
if (!startres)
{
const DWORD err = GetLastError();
if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
LOGI("The program is being run as a console application rather than as a service.");
LOGI("StartServiceCtrlDispatcher() failed with: 0x%lx", err);
return 1;
}
...
和 ServiceMain:
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
sshandle = RegisterServiceCtrlHandlerExA
(
"turboledz",
ServiceCtrlHandler,
(LPVOID)0
);
if (sshandle == NULL)
{
const DWORD err = GetLastError();
LOGI("RegisterServiceCtrlHandlerExA() failed with error 0x%lx", err);
return;
}
else
{
LOGI("Service Control Handler for TurboLEDz has been registered.");
}
...
但根据我的记录,这两个都没有达到。服务进程根本就没有启动。
因此,我找到了根本原因:服务进程从未启动,因为未找到 DLL 依赖项。 (我的MSI安装包没有打包我的服务进程依赖的DLL。)
不过,在我看来,这是 MS Windows10 中的一个错误。OS 声称有 30,000 毫秒的超时。没有超时。
StartService()
调用应该返回不同的错误,表明服务进程启动失败。
也许 ERROR_APP_INIT_FAILURE 是一个很好的错误代码。
就像现在一样,失败的启动没有正确地传达给调用者,也没有传达给事件日志。
我会看看是否可以为此向 Microsoft 记录错误。
我创建了一个 windows 服务,我安装了它:
SC_HANDLE service = CreateServiceA
(
scm,
"turboledz",
"TurboLEDz",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
servicepath,
NULL,
NULL,
NULL,
NULL,
NULL
);
这就成功了。
然后我可以查询它的状态,使用 QueryServiceStatus(service, &servstat);
可以预见 returns SERVICE_STOPPED.
到目前为止,还不错。
当我随后启动服务时,要么以编程方式使用:
const int started = StartServiceA
(
service,
0, // num service arguments.
NULL
);
if (started)
{
LOGI("turboledz service has been started.");
}
else
{
const DWORD err = GetLastError();
LOGI("Failed to start service. Error: 0x%lx", err);
return 5;
}
...或使用 sc
命令行工具:
sc start turboledz
然后我立即(在几分之一秒内)提示错误:
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
对应ERROR_SERVICE_REQUEST_TIMEOUT.
此外,由于我的服务做的第一件事是创建一个日志文件,而这个日志文件不存在,我必须得出结论,SCM 甚至没有尝试启动我的服务。
顺便说一下,该服务有一个正确设置的 binpath,所以这不是问题。
这引发了很多问题:
- TIMEOUT 怎么会瞬间失败?
- 为什么SCM没有启动服务进程?
注意:我在创建和启动服务时拥有管理员权限。
注意:这不是缺少服务可执行文件的问题,因为如果我删除它,sc 错误会变为 ERROR_SERVICE_DOES_NOT_EXIST
更新
事件查看器显示 SCM 日志,其中包含一个彻头彻尾的谎言:从服务启动到超时错误之间从未经过 30,000 毫秒。
创建、启动、超时,都发生在12:52:43。
更新 2
main() 代码:
...
SERVICE_TABLE_ENTRY servtabl[] =
{
{L"turboledz", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};
const int startres = StartServiceCtrlDispatcher( servtabl );
if (!startres)
{
const DWORD err = GetLastError();
if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
LOGI("The program is being run as a console application rather than as a service.");
LOGI("StartServiceCtrlDispatcher() failed with: 0x%lx", err);
return 1;
}
...
和 ServiceMain:
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
sshandle = RegisterServiceCtrlHandlerExA
(
"turboledz",
ServiceCtrlHandler,
(LPVOID)0
);
if (sshandle == NULL)
{
const DWORD err = GetLastError();
LOGI("RegisterServiceCtrlHandlerExA() failed with error 0x%lx", err);
return;
}
else
{
LOGI("Service Control Handler for TurboLEDz has been registered.");
}
...
但根据我的记录,这两个都没有达到。服务进程根本就没有启动。
因此,我找到了根本原因:服务进程从未启动,因为未找到 DLL 依赖项。 (我的MSI安装包没有打包我的服务进程依赖的DLL。)
不过,在我看来,这是 MS Windows10 中的一个错误。OS 声称有 30,000 毫秒的超时。没有超时。
StartService()
调用应该返回不同的错误,表明服务进程启动失败。
也许 ERROR_APP_INIT_FAILURE 是一个很好的错误代码。
就像现在一样,失败的启动没有正确地传达给调用者,也没有传达给事件日志。
我会看看是否可以为此向 Microsoft 记录错误。