我编写了一个在控制台中运行的应用程序,需要在系统关闭或用户注销之前进行快速备份.
我的测试应用程序使用信号写入文件,并在手动关闭控制台窗口时工作(单击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服务.在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;
}