By Phrxn


2020-05-22 23:17:33 8 Comments

I created a small windows service to capture some events, including the system shutdown. Every time I turn off the computer, the service event is not called. But when I restart the computer the event works normally.

I already tried to use: SERVICE_ACCEPT_PRESHUTDOWN + SERVICE_CONTROL_PRESHUTDOWN and was not successful.

How could I catch the computer shutdown event?

Ps: After compiling I register the service with the following command: sc.exe create "ZSimpleService" binPath = "C:\path\ZSimpleService.exe"

Edit 1: I'm using windows 10

Code:

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;
}

0 comments

Related Questions

Sponsored Content

7 Answered Questions

[SOLVED] How to get a specific memory address using C

13 Answered Questions

[SOLVED] Fastest method of screen capturing on Windows

  • 2011-02-21 17:22:51
  • someguy
  • 163521 View
  • 159 Score
  • 13 Answer
  • Tags:   c++ c windows

11 Answered Questions

[SOLVED] How to trigger the window resize event in JavaScript?

5 Answered Questions

24 Answered Questions

[SOLVED] What does the C++ standard state the size of int, long type to be?

  • 2009-02-26 07:59:23
  • Jérôme
  • 1225237 View
  • 695 Score
  • 24 Answer
  • Tags:   c++ c++-faq

14 Answered Questions

[SOLVED] Why does C++ not have reflection?

  • 2008-12-11 12:52:01
  • amit
  • 52226 View
  • 337 Score
  • 14 Answer
  • Tags:   c++ reflection

13 Answered Questions

[SOLVED] Why does C++ compilation take so long?

4 Answered Questions

[SOLVED] Combining C++ and C - how does #ifdef __cplusplus work?

17 Answered Questions

[SOLVED] How to capture the browser window close event?

Sponsored Content