2017-10-31 6 views
1

Ich baue das folgende Programm in VS2017/Windows 10. Wenn ich es laufen lasse, klicke ich nah und ctrl_handler() wird wie erwartet aufgerufen, aber nach ~ drei Sekunden wird der Prozess sowieso gewaltsam beendet.Warum wird der Ereignishandler für die Windows-Konsole geschlossen?

Dies ist ein Problem, weil meine reale Anwendung große Protokolldateien schreibt und drei Sekunden nicht lang genug sind, um sie auf die Festplatte zu bekommen.

Wo ist die Dokumentation, die dieses Verhalten beschreibt? Es ist nicht in those for the CTRL+CLOSE signal.

Wo wird die Zeitüberschreitung festgelegt? Kann es auf Anwendungsebene geändert werden? Oder mit einer Gruppenrichtlinie?

#include <Windows.h> 

bool mainThreadRunning; 
bool mainThreadFinished; 

BOOL ctrl_handler(DWORD event) 
{ 
    if (event == CTRL_CLOSE_EVENT) { 
     mainThreadRunning = false; 
     while (!mainThreadFinished) { 
      Sleep(100); 
     } 
     return TRUE; 
    } 
    return FALSE; 
} 

int main() 
{ 
    mainThreadRunning = true; 
    mainThreadFinished = false; 

    SetConsoleCtrlHandler((PHANDLER_ROUTINE)(ctrl_handler), TRUE); // make sure when the user hits the close button in the console we shut down cleanly 

    while (true) 
    { 

    } 

    return 0; 
} 
+1

Zum Senden eines Steuerelementereignisses fordert der Konsolenhost (conhost.exe) den Sitzungsserver (csrss.exe) zum Erstellen eines Steuerelementthreads im Client an. Dieser Thread beginnt bei 'kernelbase! CtrlRoutine' und ruft die registrierten Handler auf, bis entweder ein Handler' TRUE' zurückgibt oder der Default-Handler ('kernelbase! DefaultHandler') aufgerufen wird, der' ExitProcess (STATUS_CONTROL_C_EXIT) 'aufruft. Vista und höher erlauben es einem Handler nicht, den Prozess (und die Konsole) am Leben zu halten, indem für das Close-Ereignis "true" zurückgegeben wird. Stattdessen wartet der Sitzungsserver 5 Sekunden und beendet den Prozess, wenn er nicht beendet wurde. – eryksun

Antwort

1

Ich nehme an this is the reference Sie suchen:

Leider ist dies durch das Betriebssystem bestimmt wird. Es Dokumentation ist das Verhalten in den HandlerRoutine Callback docs beschreiben:

"In diesem Fall werden keine andere Handler-Funktionen genannt, und das System zeigt ein Popup-Dialogfeld, das den Benutzer fragt, ob den Prozess beenden Das. Das System zeigt dieses Dialogfeld auch an, wenn der Prozess nicht innerhalb eines bestimmten Zeitlimits reagiert (5 Sekunden für CTRL_CLOSE_EVENT und 20 Sekunden für CTRL_LOGOFF_EVENT oder CTRL_SHUTDOWN_EVENT). "

Es gibt keine (zumindest öffentliche, dokumentierte) API, um diese Zeitüberschreitung zu ändern.

Anmerkung:

Verfahren die SetProcessShutdownParameters Funktion verwenden können, um das System zu verhindern, dass ein Dialogfenster für den Benutzer während Logoff oder Herunterfahren anzeigt. In diesem Fall beendet das System den Prozess, wenn HandlerRoutine TRUE zurückgibt oder wenn die Zeitüberschreitungsperiode verstreicht.

Das Betriebssystem erzwingt absichtlich die Beendigung, wenn es der Ansicht ist, dass der Handler zu viel Zeit in Anspruch nimmt.

Wichtiger Hinweis gezogen von Kommentaren unten:

... Strg + C zum Time-out unterliegt (ich habe es getestet, und das ist, was ich jetzt benutze).

+2

Der Popup-Dialog für das Schließen-Ereignis ist ein Verhalten vor Vista, bei dem eine Anwendung die Konsole am Leben halten kann, indem sie für das Ereignis "Schließen" den Wert true zurückgibt. Dies wurde in Vista eliminiert.Wenn der Benutzer das Fenster schließt (oder den Prozess, der von der Konsole als sein effektiver Besitzer gemeldet wird, der 'WM_CLOSE' an das Konsolenfenster sendet), können alle der Konsole zu diesem Zeitpunkt zugeordneten Prozesse entweder beendet oder beendet werden. Niemand wird über die Angelegenheit abgestimmt. Ein Prozess kann sich nicht einmal von der Konsole lösen, um am Leben zu bleiben, da der Sitzungsserver ihn bereits für den Tod markiert hat. – eryksun

+1

Danke, das scheint alles zu sein, was MS über das Thema zu sagen beabsichtigt! Ich mag (nicht), wie der Thread eine Zeitüberschreitung zitiert, die MS seither aus der Dokumentation entfernt hat, als ob sie versuchen würde, sie zu verschleiern. ~ Aus Interesse, da CTRL_C mehrdeutig geschrieben ist, unterliegt es nicht der Auszeit (ich habe es getestet, und das ist es, was ich jetzt benutze). – sebf

+1

@sebf, es ist üblich, auch Strg + Umbruch zu verwenden, da es im Gegensatz zu Strg + C nicht ignoriert werden kann. Zum Beispiel kann ein Programm 'GenerateConsoleCtrlEvent' aufrufen, um eine Strg + C oder Strg + Break an alle an die Konsole angeschlossenen Prozesse (einschließlich sich selbst) oder eine Prozessgruppe, die mit dem' CreateProcess'-Flag 'CREATE_NEW_PROCESS_GROUP' (CMDs) erstellt wurde, zu senden 'start/B' verwendet dieses Flag). Dies kann eine Prozessgruppe ordnungsgemäß beenden. Der Lead-Prozess einer Gruppe wird jedoch erstellt, wenn Strg + C ignoriert wird. Es konnte manuell über 'SetConsoleCtrlHandler (NULL, False) 'wieder aktiviert werden, aber das kann ein Anrufer nicht steuern. – eryksun

Verwandte Themen