【问题标题】:SetConsoleCtrlHandler does not get called on shutdown关机时不调用 SetConsoleCtrlHandler
【发布时间】:2015-01-04 11:26:11
【问题描述】:

我编写了一个在控制台中运行的应用程序,需要在系统关闭或用户注销之前进行快速备份。

我的测试应用程序使用信号写入一个文件,并在手动关闭控制台窗口时工作(单击 X)。但是当控制台在关机或注销时关闭时它不起作用。根据我在 MSDN 上阅读的内容,这应该可行。

程序是用cygwin64编译的,会不会是这个问题?

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

BOOL WINAPI myHandler(DWORD signal) {
    switch(signal) {
        case CTRL_C_EVENT:
            printf("ctrl-c\n");
            break;
        case CTRL_BREAK_EVENT:
            printf("break\n");
            break;
        default:
            printf("Some other event\n");
    }

    FILE *file = fopen("windows_sig.txt", "w");
    fprintf(file, "got signal: %d\n", signal);
    fclose(file);

    return TRUE;
}

int main(int argc, char *argv[])
{
    if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)myHandler,TRUE)) {
        fprintf(stderr, "Unable to install handler!\n");
        return EXIT_FAILURE;
    }

    for (;;)
        ; //do nothing

    return EXIT_SUCCESS;
}

【问题讨论】:

标签: windows mingw handler


【解决方案1】:

好的,由于该程序打算在后台运行,因此我将其实现为 Windows 服务。在 Windows 关闭时,该服务将收到 SERVICE_CONTROL_SHUTDOWN。 该服务可以通过 sc.exe 程序安装,甚至可以通过编程方式安装。

#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

static SERVICE_STATUS sStatus;
static SERVICE_STATUS_HANDLE hServiceStatus = 0;
static int is_running = 1;
static void (*svc_main_func)();


void windows_service_control( DWORD dwControl ) {
    switch (dwControl) {
        case SERVICE_CONTROL_SHUTDOWN:
        case SERVICE_CONTROL_STOP:
            sStatus.dwCurrentState = SERVICE_STOP_PENDING;
            sStatus.dwCheckPoint = 0;
            sStatus.dwWaitHint = 3000; /* Three seconds */
            sStatus.dwWin32ExitCode = 0;
            is_running = 0;
        default:
            sStatus.dwCheckPoint = 0;
    }
    SetServiceStatus( hServiceStatus, &sStatus );
}

void windows_service_main( int argc, char **argv ) {

    hServiceStatus = RegisterServiceCtrlHandler( argv[0], (LPHANDLER_FUNCTION) windows_service_control );
    if( hServiceStatus == 0 ) {
        return;
    }

    sStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    sStatus.dwCurrentState = SERVICE_START_PENDING;
    sStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    sStatus.dwWin32ExitCode = 0;
    sStatus.dwServiceSpecificExitCode = 0;
    sStatus.dwCheckPoint = 0;
    sStatus.dwWaitHint = 3000; /* Allow us to wait three seconds */
    sStatus.dwCurrentState = SERVICE_RUNNING;

    SetServiceStatus( hServiceStatus, &sStatus );

    /* The main program */
    svc_main_func();

    /* cleanup */
    sStatus.dwCurrentState  = SERVICE_STOPPED;
    SetServiceStatus( hServiceStatus, &sStatus );
}

int windows_service_start( void (*func)() ) {
    static SERVICE_TABLE_ENTRY services[] = {
        { MAIN_SRVNAME,  (LPSERVICE_MAIN_FUNCTIONA) windows_service_main },
        { NULL, NULL }
    };

    /* Safe args for later call in windows_service_main() */
    svc_main_func = func;

    if( !StartServiceCtrlDispatcher( services ) ) {
        printf( "Can not start service: Error %d\n", GetLastError() );
        return 1;
    } else {
        return 0;
    }
}

void run() {
  while(is_running) {
    //do work
  }
}

int main() {
  windows_service_start(run);
  return 0;
}

【讨论】:

    猜你喜欢
    • 2020-08-26
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多