我正在根据以下页面上的教程编写服务: 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.
这是我的main():
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
我运行了DebugView,但从未收到“ entered main”。但是,如果我用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()的顶部获得调试消息?
答案 0 :(得分:0)
如果成功创建了服务,则应在Windows服务列表中(计算机管理->服务和应用程序->服务)看到它。如果不存在,则未正确注册。如果存在,则可以尝试从Windows服务控制台启动它。服务不会调用您的_tmain,因此不会生成日志。
答案 1 :(得分:0)
您需要使用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
);