Problème de routine SetConsoleCtrlHandler

J’écris une application console en C ++.

J’utilise SetConsoleCtrlHandler pour intercepter le bouton Fermer et CTRL + C. Cela permet à tous mes threads de s’arrêter et de sortir correctement.

L’un des threads effectue des sauvegardes nécessitant un certain temps et j’ai du code à attendre dans la routine du handle de la console. MSDN spécifie qu’une boîte devrait apparaître après 5 secondes pour CTRL_CLOSE_EVENT, mais que mon processus se termine.

C’est gênant pour le débogage de l’application de la console à mesure que le processus se termine avant que vous puissiez passer à travers et je ne sais pas quel peut être le problème (j’ai Windows 7 64 bits).

Aussi, étrangement si ma routine retourne TRUE (pour simplement désactiver l’action close), elle ferme toujours l’application. La routine est appelée, donc le SetConsoleCtrlHandler a été installé avec succès.

par exemple:

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

Des idées?

Il semble que vous ne puissiez plus ignorer les requêtes fermées sur Windows 7.

Vous obtenez cependant l’événement CTRL_CLOSE_EVENT, et à partir de ce moment, vous disposez de 10 secondes pour faire tout ce que vous devez faire avant de se fermer automatiquement. Vous pouvez donc faire tout ce que vous avez à faire dans le gestionnaire ou définir un indicateur global.

 case CTRL_CLOSE_EVENT: // CTRL-CLOSE: confirm that the user wants to exit. close_flag = 1; while(close_flag != 2) Sleep(100); return TRUE; 

Fait amusant: pendant que le code de votre événement CTRL_CLOSE_EVENT est exécuté, le programme principal continue de fonctionner. Vous pourrez donc vérifier le drapeau et faire un ‘close_flag = 2;’ quelque part. Mais rappelez-vous, vous n’avez que 10 secondes. (Donc, gardez à l’esprit que vous ne voulez pas raccrocher votre stream de programme principal en attente d’une saisie au clavier, par exemple.)

Je suspecte que ce soit sous conception sur Windows 7 – si l’utilisateur veut quitter votre application, vous n’êtes pas autorisé à lui dire “Non”.

Il n’est pas nécessaire d’attendre un drapeau du thread principal, le gestionnaire se termine dès que le thread principal se termine (ou après 10 secondes).

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

Le commentaire de Xavier est légèrement faux. Windows 7 autorise votre code dans le gestionnaire d’événements ~ 10 secondes. Si vous n’avez pas quitté le gestionnaire d’événements dans 10 secondes, vous êtes terminé. Si vous quittez le gestionnaire d’événements, vous êtes immédiatement arrêté. Renvoyer TRUE ne permet pas de poster une boîte de dialog. Il ne fait que sortir.

Vous rendez cela plus compliqué que nécessaire. Je ne sais pas exactement pourquoi votre application se ferme, mais SetConsoleCtrlHandler(NULL, TRUE) devrait faire ce que vous voulez:

http://msdn.microsoft.com/en-us/library/ms686016(VS.85).aspx

Si le paramètre HandlerRoutine a la valeur NULL, une valeur TRUE fait en sorte que le processus appelant ignore l’entrée CTRL + C et qu’une valeur FALSE restaure le traitement normal de l’entrée CTRL + C.