Ich arbeite an einem Programm, das Keyboard-Hooks verwendet. Wenn jedoch der PC, auf dem das Programm ausgeführt wird, nur leicht überlastet ist, wird Windows den Hook vom Programm trennen, sodass er nicht mehr auf Tastenanschläge reagiert.
Gibt es eine Möglichkeit, dies zu verhindern, oder sogar besser, einen anderen Weg vorzuschlagen, um genau das gleiche Problem zu lösen, indem man eine andere Architektur verwendet, vielleicht eine Pipeline einbezieht?
Sie können das nicht "erkennen", und das sollten Sie absolut nicht tun müssen. Was Sie beschreiben, ist eine Funktion, speziell eine in Windows 7 eingeführt, um Ihr System vor Rogue-Anwendungen zu schützen.
Die zutreffende Dokumentation beschreibt dies so (achten Sie besonders auf den fettgedruckten Abschnitt):
Die Hook-Prozedur sollte eine Nachricht in kürzerer Zeit verarbeiten als der Dateneintrag, der im Wert
%Vor%LowLevelHooksTimeout
im folgenden Registrierungsschlüssel angegeben ist:Der Wert ist in Millisekunden. Wenn die Hook-Prozedur abläuft, übergibt das System die Nachricht an den nächsten Hook. Unter Windows 7 und späteren Versionen wird der Hook jedoch unbeaufsichtigt entfernt, ohne dass er aufgerufen wird. Die Anwendung kann nicht erkennen, ob der Hook entfernt wurde.
Die Lösung hier ist ganz sicher nicht , um einen Weg zu finden, "zu erkennen", wenn der Hook deinstalliert und neu installiert wird. Sie sollten herausgefunden haben, dass Sie etwas falsch machen, wenn das Betriebssystem den Hook der ersten Zeit deinstalliert hat.
Die eigentliche Lösung besteht darin, Ihre Anwendung so umzugestalten, dass sie schneller vom Hook-Verfahren zurückkommt. Im Idealfall sollten Sie fast sofort zurückkehren. Wenn Sie eine Art von intensiver Berechnung als Reaktion auf die Low-Level-Nachrichten ausführen müssen (und ich kann mir nicht wirklich vorstellen, warum), dann sollten Sie die erhaltenen Informationen speichern, von der Hook-Prozedur zurückkehren und Ihre Verarbeitung bei eine spätere Zeit (wahrscheinlich in einem separaten Thread).
Tatsächlich ist das fast genau was die Dokumentation weiter vorschlägt:
Hinweis: Debug-Hooks können diesen Typ von Low-Level-Tastatur-Hooks nicht verfolgen. Wenn die Anwendung Low-Level-Hooks verwenden muss, sollten die Hooks in einem dedizierten Thread ausgeführt werden, der die Arbeit an einen Worker-Thread weiterleitet und dann sofort zurückkehrt. In den meisten Fällen, in denen die Anwendung Low-Level-Hooks verwenden muss, sollte stattdessen die Rohdateneingabe überwacht werden. Der Grund dafür ist, dass unformatierte Eingaben Maus- und Tastaturmeldungen, die auf andere Threads abzielen, asynchron besser überwachen können als Low-Level-Hooks. Weitere Informationen zur Raw-Eingabe finden Sie unter Raw-Eingabe .
Die Antwort von Cody Grey ist ausgezeichnet, aber FWIW, und rein zu Testzwecken , können Sie möglicherweise einen getrennten Hook erkennen.
Wenn Ihr Hook-Prozess aufgerufen wird, speichern Sie die aktuelle Tick-Anzahl in einer Variable, auf die der Hauptthread zugreifen kann. Rufen Sie im Hauptthread regelmäßig GetLastInputInfo
auf. Es gibt Ihnen die Tick-Anzahl für das letzte Eingabeereignis im System (nicht nur in Ihrem Prozess). Wenn der von GetLastInputInfo
bereitgestellte Wert wesentlich später (neuer) ist als die Anzahl der letzten Hook-Proc-Ticks, ist es gut anzunehmen, dass der Hook unterbrochen wurde.
Ich bin mir nicht so sicher, dass der Tastaturhaken immer Schuld ist. Wir alle scheinen zuzustimmen, dass unter idealen oder durchschnittlichen Bedingungen alles reagieren sollte. Aber während seiner Lebensdauer vom Start bis zum Herunterfahren muss ein Hook auch einige Worst-Case-Szenarien überleben. In meiner Firma haben wir einige Tastatur-Hooks geschrieben, und sie sind so leicht und asynchron wie möglich, aber sie scheinen immer noch gelegentlich getrennt zu werden.
Als Benutzer gebe ich jeden Tag mehrere zehntausend Zeichen ein. Ich reboote einmal im Monat bestenfalls, und gelegentlich bin ich schuldig, ein Windows Update zu überspringen. Mit Optionen wie Suspend und Hibernate glaube ich nicht, dass ich alleine bin. Als Entwickler muss ich sicherstellen, dass der Hook von Anfang bis Ende läuft, unabhängig davon, was mit dem System passiert.
Normalerweise reagiert mein System sehr schnell. Aber es kann kurze, außergewöhnliche Momente geben, in denen es auf den Knien ist, bis sogar Windows Aero ausgeschaltet wird. Gerade jetzt ist es sehr bissig. Wenn ich jedoch die Schaltfläche "Desktop anzeigen" drücke, wird die Maus für mindestens eine Sekunde einfrieren, während meine etwa 65 geöffneten Fenster alle zusammengebrochen sind. Was passiert, wenn ich während eines dieser Momente eine Taste drücke?
Wenn Windows die Maus für eine Sekunde einfrieren kann, wenn Windows Aero während eines kurzen Moments starker Last sogar ausschalten kann, warum kann ein Tastaturhaken nicht eine ähnliche außergewöhnliche Überlastungsdauer überstehen? Stattdessen zieht Windows aufgrund eines außergewöhnlichen Moments den Stecker und beeinflusst so stillschweigend die verbleibende Computererfahrung bis zum Herunterfahren des Systems. Für 200 ms, die nur einen Tastendruck von den Tausenden betreffen, drücken wir jeden Tag, nur für diesen Bruchteil einer Sekunde muss ich, der Benutzer, das System neu starten, weil das die einzige Art ist, die ich verstehe, wird das Tastaturmakro oder irgendein Dienstprogramm zurückbringen Ich bin auf meine produktive Arbeit angewiesen.
Auch wenn das oben Gesagte garantiert verhindert wurde (was im schlimmsten Fall darauf hindeutet, dass es nicht der Fall ist), bin ich mir nicht sicher, ob alles in einem separaten Thread erledigt werden kann. Angenommen, der Benutzer richtet einen Hotkey ein, der eine Anwendung starten soll. Kann es Gründe geben, die Anwendung aus dem aktuellen Kontext zu starten (Vordergrundfenster, Berechtigungen, etc.)? Und wäre es nicht sinnvoll, dass der Benutzer tatsächlich eine Verzögerung erwartet und akzeptiert, weil er weiß, dass er mit der Tastatur etwas begonnen hat, das länger dauert? Ich weiß nicht, ob das Beispiel technisch einwandfrei ist, aber ich wollte veranschaulichen, wie manchmal Dinge, die sonst inakzeptabel sind, aufgrund eines bekannten Ereignisses akzeptabel sein könnten.
Tastatur-Hooks können für viele Dinge sehr nützlich sein, von Makros über Fehlerkorrektur bis hin zum Starten von Dingen. Dieses in Windows 7 eingeführte Verhalten setzt das Gute und das Schlechte, das Akzeptable und das Inakzeptable, den Durchschnitt und das Außergewöhnliche im selben Korb. Dies schadet beiden Benutzern, da Qualitäts-Tastatur-Hooks getötet werden können, und Entwickler. Stellen Sie sich vor, was für ein Support-Albtraum es ist, wenn Sie keine offizielle Lösung für Ihre Anwendung haben, die unter normalen Bedingungen gut funktioniert, sondern zufällig unter schweren Belastungen (oder anderen unerklärlichen Umständen) getötet wird.
Um dies mit einer Frage abzuschließen, weiß jemand, was der Status unter Windows 8 ist, hat sich etwas geändert?
Ich denke, dass es in Ihrem Hook einige "schlechte" Performance-Codes gibt. das ist der Grund, warum leicht überladen wird.
"bewirkt, dass Windows den Hook vom Programm"
trenntErhebt sich irgendein Fehler in Ihrem Hook und Sie behandeln es nicht?
AFAIK, Windows würde den Haken nicht trennen, wenn es von selbst gut funktioniert.
Tags und Links c# windows winapi keyboard-hook setwindowshookex