在 C++ 中使用 StartService 启动服务应用程序

Start a service application using StartService in C++

我使用 Visual Studio 2013C++ 中创建了一个 windows service 应用程序。在 main() 函数中,调用另一个函数,其主体包含以下代码::

SERVICE_TABLE_ENTRY SerTable[] =
    {
        { const_cast<char *>(ServiceName.c_str()), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
        { NULL, NULL }
    };
    int res = StartServiceCtrlDispatcher(SerTable);
    if (res == 0)
    {
        DEBUG_LOG(ServiceName+":StartServiceCtrlDispatcher failed", GetLastError());
        return QERROR;
    }

我的 main() 函数还包含 system("start notepad");

我可以成功构建程序并生成可执行文件。现在我尝试使用 OpenSCManager()CreateService() 从另一个程序打开这个 exe。通过此服务创建并列在 Services.msc 下。我右键单击并启动该服务,它显示 statusstarted。但是什么也没发生..

现在,如果我双击 exe,它会显示消息:error 1063: StartServiceControldispatcher Failed,然后打开记事本。

为什么在Services.msc下启动服务时记事本打不开?

您必须从 ServiceMain 而不是 main 启动记事本。 ServiceMain 是 OS 启动服务时调用的函数,因此请将 system("start notepad") 调用移至 ServiceMain.

更多说明

作为对 OP 评论的回应 - 现在发生的错误是 1063 或 ERROR_FAILED_SERVICE_CONTROLLER_CONNECTStartServiceCtrlDispatcher 的文档解释说:

This error is returned if the program is being run as a console application rather than as a service.

这就是为什么在双击启动可执行文件时出现错误的原因 - 您将其作为控制台应用程序启动。当您正确启动服务时(从控制面板、命令提示符或 WinAPI),此功能将成功。

When the service control manager starts a service process, it waits for the process to call the StartServiceCtrlDispatcher function. The main thread of a service process should make this call as soon as possible after it starts up (within 30 seconds). If StartServiceCtrlDispatcher succeeds, it connects the calling thread to the service control manager and does not return until all running services in the process have entered the SERVICE_STOPPED state. The service control manager uses this connection to send control and service start requests to the main thread of the service process. The main thread acts as a dispatcher by invoking the appropriate HandlerEx function to handle control requests, or by creating a new thread to execute the appropriate ServiceMain function when a new service is started.

所以是的,在正确启动后,将调用 ServiceMain