SetConsoleCtrlHandler不会在关机时调用

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

我的testing应用程序用信号写一个文件,并在手动closures控制台窗口(点击X)时工作。 但是在关机或注销时closures控制台不起作用。 从我在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服务来实现。 在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; }