Windows 服务在启动时不进入_tmain

Windows service doesn't enter _tmain on startup

本文关键字:tmain 服务 启动 Windows      更新时间:2023-10-16

我正在根据以下页面的教程编写服务: https://www.codeproject.com/Articles/499465/Simple-Windows-Service-in-Cplusplus

我可以使用以下方法成功创建服务:

sc create service_name binPath=<path_name>

当我尝试启动该服务时,出现以下错误:

sc start service_name
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.

这是我的主要((:

int main (int argc, char *argv[])
{
    OutputDebugString("service_name: entered main");
    SERVICE_TABLE_ENTRY ServiceTable[] = 
    {
        {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
        {NULL, NULL}
    };
    if (StartServiceCtrlDispatcher (ServiceTable) == FALSE)
    {
        return GetLastError();
    }
    return 0;
}

编辑:我从日志文件切换到OutputDebugString((/DebugView

我运行了调试视图,但我从未收到"输入主"。但是,如果我将工作线程的内容替换为 return 语句,我确实会成功启动,并且会收到调试消息,因此我知道 DebugView 工作正常。

这是我创建工作线程的地方:

// Start a thread that will perform the main task of the service
HANDLE hThread = CreateThread (NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
if (hThread) {
    // Wait until our worker thread exits, so we can set state to SERVICE_STOPPED and return needs to stop
    WaitForSingleObject (hThread, INFINITE);
} else {
    OutputDebugString("service_name: ServiceMain: CreateThread returned NULL");
}

似乎我的工作线程负责启动错误,但是为什么我不会在main((的顶部收到调试消息?

如果您的服务已成功创建,则应在 Windows 服务(计算机管理 -> 服务和应用程序 ->服务(列表中看到它。如果它不存在,则它未正确注册。如果存在,您可以尝试从 Windows 服务控制台启动它。您的_tmain只是不被服务调用,不会生成日志。

您需要使用 SetServiceStatus 函数更新 SCM 状态。

如果初始化服务需要很长时间,则应使用SERVICE_START_PENDING状态定期更新状态。

初始化完成后,必须将 SCM 状态更新为SERVICE_RUNNING。

其他状态是:

-SERVICE_STOP_PENDING。

-SERVICE_PAUSE_PENDING。

-SERVICE_CONTINUE_PENDING。

-SERVICE_STOPPED。

将状态发送到 SCM 的函数如下所示:

BOOL SendStatusToSCM
                    (
                    DWORD dwCurrentState,
                    DWORD dwWin32ExitCode, 
                    DWORD dwServiceSpecificExitCode,
                    DWORD dwCheckPoint,
                    DWORD dwWaitHint
                    )
{
BOOL success;
SERVICE_STATUS serviceStatus;
// Preenche os campos do service status
serviceStatus.dwServiceType     = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwCurrentState    = dwCurrentState;
if (dwCurrentState == SERVICE_START_PENDING)
    serviceStatus.dwControlsAccepted = 0;
else
    serviceStatus.dwControlsAccepted = 
        SERVICE_ACCEPT_STOP |
        SERVICE_ACCEPT_PAUSE_CONTINUE |
        SERVICE_ACCEPT_SHUTDOWN;
if (dwServiceSpecificExitCode == 0)
    serviceStatus.dwWin32ExitCode =
        dwWin32ExitCode;
else
    serviceStatus.dwWin32ExitCode = 
        ERROR_SERVICE_SPECIFIC_ERROR;
serviceStatus.dwServiceSpecificExitCode =
    dwServiceSpecificExitCode;
serviceStatus.dwCheckPoint = dwCheckPoint;
serviceStatus.dwWaitHint = dwWaitHint;
// Passa o status para o SCM
success = SetServiceStatus
                            (
                            serviceStatusHandle,
                            &serviceStatus
                            );
if (!success)
    exit( 99 );
return success;
}

通过下面的创建,启动服务可以完美运行,并始终激活main((:

serv=CreateService (

sc,
noServ,                     //  service name
noDisp,                     //  display name
SERVICE_ALL_ACCESS,         //  desired access
SERVICE_WIN32_OWN_PROCESS,  //  service type
SERVICE_AUTO_START,         //  modo de iniciar o serviço
SERVICE_ERROR_NORMAL,       //  gravidade da falha do serviço
noExec,                     //  nome do executável
NULL,                       //  nome do grupo ao qual pertence
NULL,                       //  tag id
NULL,                       //  tabela de dependências
NULL,                       //  account name 
NULL                        //  account password
);