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,所以这不是问题。

这引发了很多问题:

  1. TIMEOUT 怎么会瞬间失败?
  2. 为什么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 记录错误。