Frage

Ich weiß, dass ich setconsolehandler() verwenden, wenn ich Konsole Schließereignisse verwalten möchten.

Ich weiß nicht, wie die CTRL_CLOSE_EVENT zu blockieren. Ich habe falsch / wahr versucht, Rückkehr, wenn er dieses Ereignis fängt, aber kein Erfolg

Hier ist, was ich habe bisher (danke Anton Gogolev!)

[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

public delegate bool HandlerRoutine(CtrlTypes CtrlType);

public enum CtrlTypes{
    CTRL_C_EVENT = 0,
    CTRL_BREAK_EVENT,
    CTRL_CLOSE_EVENT,
    CTRL_LOGOFF_EVENT = 5,
    CTRL_SHUTDOWN_EVENT
}

private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{ 
    if(ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
        return false;// I have tried true and false and viceversa with the return   
                     // true/false but I cant seem to get it right.
    return true;
}


//and then I use this to call it
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

Auch ist es möglich, einen neuen Thread zu überwachen, um zu laufen, wenn die Konsole und Block endet, die schließen, wenn der Haupt-Thread in der Mitte ist, etwas zu tun?

War es hilfreich?

Lösung

Die Dokumentation für SetConsoleCtrlHandler() sagt:

  

Das System erzeugt CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT und CTRL_SHUTDOWN_EVENT Signale, wenn der Benutzer die Konsole schließt, abmeldet, oder das System heruntergefahren, so dass das Verfahren eine Möglichkeit vor Beendigung aufzuräumen hat.

Dies bedeutet, dass im Gegensatz zu, wenn STRG + C oder STRG + UNTBR Behandlung von Ereignissen, Ihr Prozess nicht die Möglichkeit erhalten, das engen, Abmelden oder Herunterfahren abzubrechen.

Andere Tipps

Eigentlich kann man es blockieren (ich das unter Windows XP mindestens reproduziert). Zum Beispiel, wenn in Ihrem Handler haben Sie eine endlose while-Schleife mit einem Schlaf, das diesen Prozess von Beenden stoppt immer (oder zumindest für eine lange Zeit, oder bis der Benutzer tötet den Prozess durch die Task-Manager).

Wenn Sie wirklich einen Thread benötigt, um zu starten, können Sie einen Wartezustand (AutoResetEvent in C #) verwenden und Ihren Thread starten (wenn auch ein neuer Thread wahrscheinlich nicht erforderlich ist, in den meisten Fällen), dann die Bedingung Warte benachrichtigt, wenn Ihr Thread fertig. Allerdings nur in der Prozedur jede Bereinigung tun würde in den meisten Fällen ausreichen.

Wenn im schlimmsten Fall, dass Sie ewig warten haben, wird der Prozess läuft bleiben und Sie werden in der Lage, es zu sehen, wenn Sie in (zumindest unter Windows XP) wieder anmelden. Dies führt jedoch zu dem Desktop für etwa 20 Sekunden warten, bevor Sie mit dem ausloggen Bildschirm gehe (während es wartet auf Ihre applicaiton verlassen), und pausiert dann wieder im Abmeldebildschirm (ich nehme an, während es für ein zweites Mal versucht) . Natürlich, wir raten dringend ewig warten; für jede lange Lauf Sachen sollten Sie in einem Dienst gestellt wirklich.

fand ich eine mögliche ‚Hack‘, die die Anwendung von Schließung verhindern könnte, während immer noch ordentlich die Konsole schließen Anfrage zu gehorchen. Insbesondere ist dies geeignet, glaube ich, für die GUI-Anwendungen, die eine Konsole als ‚Extra‘ geschaffen haben. Aus der MSDN-Dokumentation, an der Stelle, wo die Strg-Handler ein neuen Thread genannt wird wird in dem Prozess erstellt die Prozedur aufzurufen. Meine Lösung, dann ist das Angreifen eindringenden Thread zu töten, bevor der Standard-Handler Exitprocess aufrufen können. In der Behandlungsroutine (Code in C ++):

// Detach Console:
FreeConsole();
// Prevent closing:
ExitThread(0);
return TRUE; // Not reached

EDIT: Es scheint dies einige Probleme verursacht, wie zu erwarten, nehme ich an. Ein nachfolgender Aufruf von AllocConsole () hängt auf unbestimmte Zeit, so vermute ich, dass der Faden vorzeitig verlässt nicht richtig aufzuräumen.

EDIT 2:

oben Um zu klären, ich habe keine direkten Probleme gefunden mit weiterhin das Programm auszuführen. Aber bedenken Sie, dass wir mit Nachdruck einen Thread beendet haben, die erstellt KERNEL32 hat, so dass alle Ressourcen innerhalb kernel32 in einem unbestimmten Zustand sein könnten. Dies könnte unvorhergesehene Probleme verursachen, wenn das Programm läuft weiter.

Meistens denke ich, werden diese Probleme auf die Konsole API verwendet werden. Wie erwähnt, nicht AllocConsole von diesem Punkt arbeitet an (es wird die Anwendung hängt), so dass das Programm nicht um eine neue Konsole öffnen. Es ist sehr gut möglich, dass auch andere Funktionen der Konsole als auch fehlschlagen. Im Grunde alles, was Sie von diesem Punkt tun ab, dass in irgendeiner Weise (direkt oder indirekt) ruft in kernel32 unterworfen ist nicht definiertes Verhalten, aber ich vermute, dass in der Praxis wird es keine Probleme sein außerhalb der Konsole Funktionen.

Meine Schlussfolgerung ist, dass man, wenn überhaupt möglich, dieses Verfahren vermeiden sollte, aber wenn eine vorzeitige Beendigung schlimmer ist, so kann dies gedacht werden als Notfall-Work-around, sparsam und mit Vorsicht verwendet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top