Windows服务实现 - 错误1053:服务未及时响应启动或控制请求

时间:2015-08-01 17:31:55

标签: c windows service

我正在尝试在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;
}

可能有任何想法吗?

提前致谢,

1 个答案:

答案 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());
}

// ...