问题
I'm writting a console application in C++.
I use SetConsoleCtrlHandler to trap close and CTRL+C button. This allows for all my threads to stop and exit properly.
One of the thread performs some saving that require some time to complete and I have some code to wait in the console crtl handle routine. MSDN specify that a box should pop up after 5 seconds for CTRL_CLOSE_EVENT, but instead my process exits.
This is annoying for debugging console application too as the process exits before you can step through and I don't know what may be the problem (I have Windows 7 64bits).
Also, strangely if my routine returns TRUE (to simply disable the close action), it still closes the application. The routine does get called, so the SetConsoleCtrlHandler was successful installed.
e.g.:
BOOL WINAPI ConsoleHandlerRoutine(DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT)
{
return TRUE;
}
return FALSE;
}
int _tmain(int argc, _TCHAR* argv[])
{
BOOL ret = SetConsoleCtrlHandler(ConsoleHandlerRoutine, TRUE);
while (true)
{
Sleep(1000);
}
return 0;
}
Any ideas?
回答1:
It looks like you can no longer ignore close requests on Windows 7.
You do get the CTRL_CLOSE_EVENT event though, and from that moment on, you get 10 seconds to do whatever you need to do before it auto-closes. So you can either do whatever work you need to do in the handler or set a global flag.
case CTRL_CLOSE_EVENT: // CTRL-CLOSE: confirm that the user wants to exit.
close_flag = 1;
while(close_flag != 2)
Sleep(100);
return TRUE;
Fun fact: While the code in your CTRL_CLOSE_EVENT event runs, the main program keeps on running. So you'll be able to check for the flag and do a 'close_flag = 2;' somewhere. But remember, you only have 10 seconds. (So keep in mind you don't want to hang up your main program flow waiting on keyboard input for example.)
回答2:
I suspect that this is by-design on Windows 7 - if the user wants to quit your application, you're not allowed to tell him "No".
回答3:
There is no need to wait for any flag from the main thread, the handler terminates as soon as the main thread exits (or after 10s).
BOOL WINAPI ConsoleHandler(DWORD dwType)
{
switch(dwType) {
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
set_done();//signal the main thread to terminate
//Returning would make the process exit!
//We just make the handler sleep until the main thread exits,
//or until the maximum execution time for this handler is reached.
Sleep(10000);
return TRUE;
default:
break;
}
return FALSE;
}
回答4:
Xavier's comment is slightly wrong. Windows 7 allows your code in the event handler ~10 seconds. If you haven't exited the event handler in 10 seconds you are terminated. If you exit the event handler you are terminated immediately. Returning TRUE does not post a dialog. It just exits.
回答5:
You're making this more complicated than it needs to be. I don't know exactly why your app is closing, but SetConsoleCtrlHandler(NULL, TRUE) should do what you want:
http://msdn.microsoft.com/en-us/library/ms686016(VS.85).aspx
If the HandlerRoutine parameter is NULL, a TRUE value causes the calling process to ignore CTRL+C input, and a FALSE value restores normal processing of CTRL+C input.
来源:https://stackoverflow.com/questions/3640633/setconsolectrlhandler-routine-issue