Windows Service在将字符集设置为unicode时工作正常,但是具有多字节的相同代码开始失败并出现1053错误

时间:2019-05-10 18:01:52

标签: unicode windows-services

使用发行版配置+ Unicode字符集的C ++中的基本Windows服务示例代码可以在管理控制台中使用sc start cmd完美启动,但是当我更改配置release +多字节时,比sc start cmd失败,出现最常见的服务错误:1053 -该服务未及时响应启动或控制请求。

我不知道此unicode与多字节配置之间的关系是什么。甚至我都对每个函数后缀进行了交叉检查,这在unicode模式后缀中是W而在多字节模式后缀中是A


#define SERVICE_NAME    "USB Device Monitor Service"
#define SLEEP_TIME  (1000)

void main()
{
    SERVICE_TABLE_ENTRY ServiceTable[1];
    ServiceTable[0].lpServiceName = SERVICE_NAME;
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

    StartServiceCtrlDispatcher(ServiceTable);
}

void ServiceMain()
{
    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
    Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    Status.dwCurrentState = SERVICE_START_PENDING;
    Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    Status.dwWin32ExitCode = 0;
    Status.dwServiceSpecificExitCode = 0;
    Status.dwCheckPoint = 0;
    Status.dwWaitHint = 0;

    hStatus = RegisterServiceCtrlHandlerEx(SERVICE_NAME, (LPHANDLER_FUNCTION_EX)ControlHandler, 0);

    if ((SERVICE_STATUS_HANDLE)0 == hStatus)
    {
        // Error
    }
    SetServiceStatus(hStatus, &Status);

    Status.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hStatus, &Status);

    ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;

    // Initialization
    hDeviceNotify = RegisterDeviceNotification((HANDLE)hStatus, &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);

    if (NULL == hDeviceNotify)
    {
        // Error
    }

    while (SERVICE_RUNNING == Status.dwCurrentState)
    {
        Sleep(SLEEP_TIME);
    }
}

DWORD ControlHandler(DWORD dwControl, DWORD dwEventType,
    LPVOID lParam, LPVOID lpContext)
{
    switch (dwControl)
    {
    case SERVICE_CONTROL_SHUTDOWN:
    case SERVICE_CONTROL_STOP:
        UnregisterDeviceNotification(hDeviceNotify);
        Status.dwCurrentState = SERVICE_STOPPED;
        SetServiceStatus(hStatus, &Status);
        CloseHandle(hPipe);
        return NO_ERROR;

    case SERVICE_CONTROL_DEVICEEVENT:
        if ((DBT_DEVICEARRIVAL == dwEventType) || (DBT_DEVICEREMOVECOMPLETE == dwEventType))
        {
            try
            {
                DEV_BROADCAST_HDR* header = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
                if (DBT_DEVTYP_DEVICEINTERFACE == header->dbch_devicetype)
                {
                    //parse intrested USB device only
                }
            }
            catch (const std::nullptr_t /*ex*/)
            {
                //"ERROR: Processing WM_DEVICECHANGE failed
            }
        }
        break;
    default:
        //"ERROR : Unknown dwControl: dwControl)
        SetServiceStatus(hStatus, &Status);
        break;
    }

    return NO_ERROR;
}

1 个答案:

答案 0 :(得分:0)

您的ServiceMain()ControlHandler()函数被声明为错误,但是您正在使用类型转换来阻止编译器发出抱怨。每当您不得不使用类型转换来使编译器安静时,请考虑您的代码正在尝试做什么,因为它可能做错了事。

此外,您传递给StartServiceCtrlDispatcher()SERVICE_TABLE_ENTRY[]数组是不完整的-您不能像文档中所说的那样以NULL终止数组。

为此,您声称您的服务在为Unicode编译时可以工作,但是您显示的代码实际上不会在Unicode下编译,因为ServiceTable[0].lpServiceName字段将使用Unicode字符串,但显示的代码而是分配一个ANSI字符串,这是一个错误。

我建议您阅读Microsoft的文档,并密切注意它提供的示例:

Service Program Tasks

  

以下任务由service programs执行:

           

相关主题

     

The Complete Service Sample

话虽如此,请尝试以下类似操作:

#define SERVICE_NAME    TEXT("USB Device Monitor Service")

HANDLE hStopEvent = NULL;
SERVICE_STATUS_HANDLE hStatus = NULL;

SERVICE_STATUS Status;

DWORD WINAPI ControlHandler(DWORD dwControl, DWORD dwEventType,
    LPVOID lParam, LPVOID lpContext)
{
    switch (dwControl)
    {
        case SERVICE_CONTROL_INTERROGATE:
            return NO_ERROR;

        case SERVICE_CONTROL_STOP:
        case SERVICE_CONTROL_SHUTDOWN:
            SetEvent(hStopEvent);
            return NO_ERROR;

        case SERVICE_CONTROL_DEVICEEVENT:
            if ((DBT_DEVICEARRIVAL == dwEventType) || (DBT_DEVICEREMOVECOMPLETE == dwEventType))
            {
                try
                {
                    DEV_BROADCAST_HDR* header = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
                    if (DBT_DEVTYP_DEVICEINTERFACE == header->dbch_devicetype)
                    {
                        //parse intrested USB device only
                    }
                }
                catch (const std::nullptr_t /*ex*/)
                {
                    //"ERROR: Processing WM_DEVICECHANGE failed
                }
            }
            break;

        default:
            //"ERROR : Unknown dwControl: dwControl)
            break;
    }

    return NO_ERROR;
}

void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
    hStatus = RegisterServiceCtrlHandlerEx(SERVICE_NAME, &ControlHandler, 0);
    if (!hStatus)
    {
        // Error
        return;
    }

    ZeroMemory(&Status, sizeof(Status));
    Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    Status.dwCurrentState = SERVICE_START_PENDING;
    SetServiceStatus(hStatus, &Status);

    // Initialization

    hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!hStopEvent)
    {
        // Error
        Status.dwCurrentState = SERVICE_STOPPED;
        Status.dwWin32ExitCode = GetLastError();
        SetServiceStatus(hStatus, &Status);
        return;
    }

    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
    ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;

    HDEVNOTIFY hDeviceNotify = RegisterDeviceNotification((HANDLE)hStatus, &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);
    if (!hDeviceNotify)
    {
        // Error
        Status.dwCurrentState = SERVICE_STOPPED;
        Status.dwWin32ExitCode = GetLastError();
        SetServiceStatus(hStatus, &Status);
        return;
    }

    Status.dwCurrentState = SERVICE_RUNNING;
    Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    SetServiceStatus(hStatus, &Status);

    WaitForSingleObject(hStopEvent, INFINITE);

    Status.dwCurrentState = SERVICE_STOP_PENDING;
    Status.dwControlsAccepted = 0;
    SetServiceStatus(hStatus, &Status);

    UnregisterDeviceNotification(hDeviceNotify);
    CloseHandle(hStopEvent);

    Status.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus(hStatus, &Status);
}

int main()
{
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = SERVICE_NAME;
    ServiceTable[0].lpServiceProc = &ServiceMain;
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;

    StartServiceCtrlDispatcher(ServiceTable);

    return 0;
}