我正在尝试在C中制作一个小型Windows服务,但却陷入了问题所在。一旦我在Windows服务中启动它,我收到错误:
“Windows无法在本地计算机上启动MyService服务。 错误1053:服务未及时响应启动或控制请求。“
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "log.h"
#define SERVICE "MyService"
#define SERVICE_UNKNOW 0x00000000
#define SERVICE_REFRESH 0xFFFFFFFF
SERVICE_STATUS_HANDLE serviceHandle;
void ServiceUpdateStatus(SERVICE_STATUS_HANDLE serviceHandle, DWORD newState)
{
static SERVICE_STATUS serviceStatus;
if (newState == SERVICE_UNKNOW)
{
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwWaitHint = 0;
newState = SERVICE_STOPPED;
}
switch(newState)
{
case SERVICE_START_PENDING:
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service start pending");
break;
case SERVICE_RUNNING:
serviceStatus.dwCurrentState = SERVICE_RUNNING;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service running");
break;
case SERVICE_STOP_PENDING:
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service stop pending");
break;
case SERVICE_STOPPED:
serviceStatus.dwCurrentState = SERVICE_STOPPED;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service stopped");
break;
case SERVICE_REFRESH:
SetServiceStatus(serviceHandle, &serviceStatus);
break;
}
}
void WINAPI ServiceControlHandler(DWORD controlCode)
{
switch (controlCode)
{
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
/* stop service */
ServiceUpdateStatus(serviceHandle, SERVICE_STOP_PENDING);
make_ServiceMainThread_to_return();
WSACleanup();
/* stopped */
ServiceUpdateStatus(serviceHandle, SERVICE_STOPPED);
break;
}
ServiceUpdateStatus(serviceHandle, SERVICE_REFRESH);
}
DWORD ServiceMainThread(LPVOID parameters)
{
do_something_and_never_return();
return EXIT_SUCCESS;
}
VOID WINAPI ServiceMain(DWORD argc, char *argv[])
{
WSADATA wsa;
HANDLE mainThread;
serviceHandle = RegisterServiceCtrlHandler(SERVICE, ServiceControlHandler);
if(!serviceHandle)
{
add_log("Error: RegisterServiceCtrlHandler, error %u", (unsigned int)GetLastError());
return;
}
/* init service */
ServiceUpdateStatus(serviceHandle, SERVICE_START_PENDING);
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
add_log("Error: WSAStartup, error %u", (unsigned int)GetLastError());
return;
}
mainThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ServiceMainThread, NULL, 0, NULL);
if (mainThread == NULL)
{
ServiceUpdateStatus(serviceHandle, SERVICE_STOPPED);
add_log("Error: Unable to create service thread, error %u", (unsigned int)GetLastError());
return;
}
add_log("Service main thread: %u", (unsigned int)mainThread);
CloseHandle(mainThread);
/* run service */
ServiceUpdateStatus(serviceHandle, SERVICE_RUNNING);
}
void LaunchService()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = SERVICE;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
if (!StartServiceCtrlDispatcher(ServiceTable))
{
add_log("Error: StartServiceCtrlDispatcher, error %u", (unsigned int)GetLastError());
}
}
void InstallService()
{
SC_HANDLE scManager;
char path[MAX_PATH+1];
scManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE );
if (scManager)
{
if (GetModuleFileName( 0, path, sizeof(path)) > 0)
{
SC_HANDLE service;
service = CreateService(scManager, SERVICE, SERVICE, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, 0, 0, 0, 0, 0 );
if (service)
CloseServiceHandle(service);
}
CloseServiceHandle(scManager);
}
}
void UninstallService()
{
SC_HANDLE scManager;
SC_HANDLE scService;
SERVICE_STATUS serviceStatus;
scManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );
if (scManager)
{
scService = OpenService(scManager, SERVICE, SERVICE_QUERY_STATUS|DELETE);
if (scService)
{
if (QueryServiceStatus(scService, &serviceStatus))
{
if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
DeleteService(scService);
}
CloseServiceHandle(scService);
}
CloseServiceHandle(scService);
}
}
int main(int argc, char *argv[])
{
if(strcmpi(argv[1], "install") == 0)
{
InstallService();
return EXIT_SUCCESS;
}
else if(strcmpi(argv[1], "uninstall") == 0)
{
UninstallService();
return EXIT_SUCCESS;
}
LaunchService();
return EXIT_SUCCESS;
}
可能有任何想法吗?
提前致谢,
答案 0 :(得分:1)
我发现了这个问题。 在* _PENDING操作期间,我们必须指定dwWaitHint字段。
SetServiceStatus因此报告错误,并且从不更新服务状态。
我更正的功能ServiceUpdateStatus:
#define SERVICE_REFRESH 0xFFFFFFFF
// ...
void ServiceUpdateStatus(DWORD newState)
{
static SERVICE_STATUS serviceStatus;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
switch(newState)
{
case SERVICE_START_PENDING:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 1;
serviceStatus.dwWaitHint = 1000;
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
add_log("Service start pending");
break;
case SERVICE_RUNNING:
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwCurrentState = SERVICE_RUNNING;
add_log("Service running");
break;
case SERVICE_STOP_PENDING:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 1;
serviceStatus.dwWaitHint = 1000;
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
add_log("Service stop pending");
break;
case SERVICE_STOPPED:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwCurrentState = SERVICE_STOPPED;
add_log("Service stopped");
break;
case SERVICE_REFRESH:
if (serviceStatus.dwCurrentState == SERVICE_STOP_PENDING &&
serviceStatus.dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwCheckPoint++;
break;
}
if (!SetServiceStatus(serviceHandle, &serviceStatus))
add_log("SetServiceStatus failed, error %u", GetLastError());
}
// ...