Windows服务无法捕获关闭事件C / C ++

问题描述 投票:1回答:1

我创建了一个小型Windows服务来捕获某些事件,包括系统关闭。每次关闭计算机时,不会调用服务事件。但是,当我重新启动计算机时,事件正常进行。

我已经尝试使用:SERVICE_ACCEPT_PRESHUTDOWN + SERVICE_CONTROL_PRESHUTDOWN,但未成功。

我如何捕获计算机关闭事件?

Ps:编译后,我使用以下命令注册了服务:sc.exe创建“ ZSimpleService” binPath =“ C:\ path \ ZSimpleService.exe”

编辑1:我正在使用Windows 10

代码:

SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;

VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
DWORD WINAPI CtrlHandlerEx(DWORD CtrlCode, DWORD eventType, LPVOID eventData, LPVOID context);

#define SERVICE_NAME _T("ZSimpleService")

VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) {

    g_StatusHandle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, CtrlHandlerEx,
    NULL);

    if (g_StatusHandle == NULL) {
        goto EXIT;
    }

    // Tell the service controller we are starting
    ZeroMemory( & g_ServiceStatus, sizeof(g_ServiceStatus));

    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
            | SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SESSIONCHANGE
            | SERVICE_ACCEPT_SHUTDOWN;
    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwServiceSpecificExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 0;

    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
        //...
    }

    g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (g_ServiceStopEvent == NULL) {
        //...
        goto EXIT;
    }

    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 0;

    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
        //...
    }

    HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);

    WaitForSingleObject(hThread, INFINITE);

    CloseHandle(g_ServiceStopEvent);

    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    g_ServiceStatus.dwWin32ExitCode = 0;
    g_ServiceStatus.dwCheckPoint = 3;

    if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {

    }

    EXIT: return;
}

void suspending() {
    FILE *file = fopen("C:\\test\\suspending.txt", "w+");
    if (file)
        fprintf(file, "...");
}

void logoff() {
    FILE *file = fopen("C:\\test\\logoff.txt", "w+");
    if (file)
        fprintf(file, "...");
}

void lock_session() {
    FILE *file = fopen("C:\\test\\lock_session.txt", "w+");
    if (file)
        fprintf(file, "...");
}

void poweroff() {
    FILE *file = fopen("C:\\test\\poweroff.txt", "w+");
    if (file)
        fprintf(file, "...");
}

DWORD WINAPI CtrlHandlerEx(DWORD CtrlCode, DWORD eventType, LPVOID eventData,
        LPVOID context) {
    switch (CtrlCode) {

    case SERVICE_CONTROL_STOP: {
        g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
        g_ServiceStatus.dwWin32ExitCode = 0;
        g_ServiceStatus.dwCheckPoint = 0;
        g_ServiceStatus.dwWaitHint = 0;

        if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
            //...
        }

        SetEvent(g_ServiceStopEvent);

        return NO_ERROR;
    }
    case SERVICE_CONTROL_POWEREVENT: {
        if (eventType == PBT_APMQUERYSUSPEND) {
            //Computer is suspending
            suspending();

        }
        return NO_ERROR;
    }
    case SERVICE_CONTROL_SESSIONCHANGE: {
        switch (eventType) {
        case WTS_SESSION_LOGOFF:
            //User is logging off
            logoff();
            break;
        case WTS_SESSION_LOCK:
            //User locks the session
            lock_session();
            break;
        }
        return NO_ERROR;
    }
    case SERVICE_CONTROL_SHUTDOWN: {
        //Computer is shutting down
        poweroff();

        return NO_ERROR;
    }
    default:
        return ERROR_CALL_NOT_IMPLEMENTED;
    }

}

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) {

    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0) {

        //many cool code....

        Sleep(3000);
    }

    return 0;
}

DWORD RunService() {
    SERVICE_TABLE_ENTRY serviceTable[] = { { SERVICE_NAME, ServiceMain },
            { 0, 0 } };

    if (StartServiceCtrlDispatcher(serviceTable)) {
        return 0;
    } else {
        DWORD erro = GetLastError();

        //handler erro...

        return 1;
    }
}

int _tmain(int argc, TCHAR *argv[]) {
    RunService();
    return 0;
}
c++ c winapi events service
1个回答
0
投票

启用快速启动选项后,单击开始菜单->关机将使计算机进入睡眠模式/休眠模式,而不是关机。但是重新启动菜单不受影响。 (并且从命令行关闭也不会像我们已经发现的那样受到影响。)

因此您可以禁用快速启动来解决此问题。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.