2016-07-25 20 views
0

Ich habe ein kleines Python-Skript, das Statistiken über meine Tastatur und Maus Verwendung auf einem Windows-Rechner sammelt.Detect SetWindowsHookExA WH_MOUSE_LL Trennen/Unhooking

Ich habe es über windll.user32.SetWindowsHookExA(win32con.WH_MOUSE_LL, mouse_pointer, win32api.GetModuleHandle(None), 0) eingerichtet. Ich schreibe das, damit Sie sehen können, welche API ich verwende. Es könnte genauso gut ein C++ Programm gewesen sein.

Es funktioniert vollkommen gut, mit einer Ausnahme: Wenn ich Android Studio verwenden, um eine App zu kompilieren, mein Core i7 mit 4 Kernen maximiert bei 100% auf allen Kernen, reagiert die Maus und das Betriebssystem im Allgemeinen nicht mehr ein bekanntes Problem mit Android Studio.

Normalerweise, wenn eine solche sehr hohe CPU-Last für ein paar Sekunden (4+) auftritt, wird der WH_MOUSE_LL-Hook vom Betriebssystem getrennt, als würde er sagen "Nein, wir haben keine Zeit für Sie, wir" re enfernen Sie“

ich das nicht auf Python Schuld, weil ich auch ein Lautstärke-Manager PowerMixer genannt haben, die offenbar auch eine Maus-Hook registriert, so dass er Mausrad Aktionen auf der unteren Taskleiste verfolgen können (Explorer .exe Shell_TrayWnd) und diese Anwendung verliert auch die Fähigkeit, diesen Maus-Hook nach dem Kompilieren zu verwenden.

Wenn ich das Scrollrad kompiliere und ständig scrolle (nur zum Spaß), fängt der Computer an zu piepsen, wie in einem sehr niedrigen Systempiepston und dann werden auch die Tastatur-Hooks nicht registriert.

Wie kann ich über die Windows API erkennen, ob meine Haken gelöst/ausgehakt wurden? Ich benötige keine Python-spezifische Antwort, nur Informationen zur richtigen Verwendung des Win32-APIs.

Der Bemerkungen Abschnitt des SetWindowsHookEx documentation sagt:

Wenn die Hook-Prozedur abläuft, das System die Nachricht an den nächsten Haken geht. Unter Windows 7 und späteren Versionen wird der Hook jedoch unbeaufsichtigt entfernt, ohne dass er aufgerufen wird. Es gibt keine Möglichkeit für die Anwendung wissen, ob der Haken entfernt ist.

Bin ich kein Glück hier?

Update: Ein paar Wochen später möchte ich nur informieren, dass Hans Passan Vorschlag sehr gut funktioniert. Ich empfehle das. Während 10.000 ms ein bisschen hoch erscheinen, habe ich es auf diesen Wert eingestellt und habe keine negativen Auswirkungen. Dies ist der Weg, das Problem systemweit innerhalb weniger Minuten zu lösen.

+1

Erhöhen Sie einfach das Timeout, es ist Registrierungseinstellung. Fügen Sie dem Schlüssel HKEY_CURRENT_USER \ Control Panel \ Desktop den Wert LowLevelHooksTimeout, ein DWORD, hinzu. Setzen Sie es auf 10000, um das Zeitlimit zu verdoppeln. –

+0

* "Ich mache das nicht auf Python aus, weil ich auch [ein anderes Programm, das unter denselben Bedingungen dasselbe Verhalten zeigt, die gleiche Bibliothek benutzen]" *. - Das scheint ziemlich ergebnislos zu sein, und ich würde nichts als Quelle mit dieser kleinen Information verwerfen. Ziehen Sie einen Minidump sowohl von Android Studio als auch von Ihrem Python-Skript, wenn sie fehlschlagen, und analysieren Sie sie später. Dies kann interessante Informationen preisgeben. – IInspectable

+0

@Intensiv Sie können Recht haben. Aber das Debuggen dieses Problems ist mir die Zeit und Mühe nicht wert. Es war eine schnelle Entscheidung aufgrund der Tatsache, dass dieser Sound-Manager, den ich erwähne, auch das gleiche Problem hat und dass man definitiv nicht in Python geschrieben ist. –

Antwort

2

Wie kann ich über die Windows API feststellen, ob meine Haken gelöst/ausgehakt wurden?

Es gibt keine direkte Weise es, und Ihre eigene Frage zitierte die MSDN-Dokumentation, die es sichert zu tun up:

Wenn die Hook-Prozedur abläuft, übergibt das System die Nachricht an die nächster Haken. Unter Windows 7 und höher, , wird der Hook jedoch unbeaufsichtigt entfernt, ohne dass er angerufen wird. Die Anwendung kann nicht erkennen, ob der Haken entfernt wurde.

jedoch eine indirekte Weg könnte sein, den Haken zu haben, sich an das letzte Mal halten sie genannt wird, und dann Haupt-app/script kann GetLastInputInfo() regelmäßig aufrufen und diese Zeit zu Ihrer nachverfolgt Zeit vergleichen. Wenn der Unterschied eine signifikante Marge höher ist als das Hook-Timeout, das in der Registry gespeichert ist (siehe documentation), ist es wahrscheinlich eine gute Wette, dass Ihr Hook möglicherweise verschwunden ist.

Das folgende MSDN-Blog erklärt die Details des Haken Timeout:

Global hooks getting lost on Windows 7

Aber am wichtigsten ist, heißt es:

Meine Empfehlung ist, dass niedriges Niveau Haken soll vermieden werden wann immer möglich. Wenn Sie Tastenanschläge überwachen (und nicht versuchen, sie zu blockieren), können Sie die Tastatureingabe über die Roheingabe erhalten. Dies ist leichter als Hooks, hat keine Auswirkungen auf die Reaktionsfähigkeit anderer Apps und wird nicht deaktiviert, wenn die App nicht reagiert.

die die gleichen wie Microsofts eigene Empfehlung in den LowLevelMouseProc() und LowLevelKeyboardProc() Dokumentationen ist:

Wenn die Anwendung geringe Haken verwenden müssen, sollten sie die Haken auf einem eigenen Thread ausgeführt, der die Arbeit weg geht zu einem Worker-Thread und dann sofort zurück. In den meisten Fällen, in denen die Anwendung Low-Level-Hooks verwenden muss, sollte sie stattdessen die rohe Eingabe überwachen. 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 Roheingabe finden Sie unter Raw Input.

+0

Danke, das ist sehr hilfreich. Ich habe das Timeout erhöht, wie Hans Passant kommentierte, und anscheinend funktioniert das. Wenn das Problem immer noch auftritt, werde ich definitiv das 'GetLastInputInfo()' Ding machen, da ich auch einen Timer verwende, der alle 15 Sekunden aufgerufen wird, der die gesammelten Daten analysiert und in einer Datenbank speichert. Dieser Ort wäre der perfekte Ort für diese Funktionalität. Auch danke für die Links und zusätzliche Informationen, ich könnte zu der Raw Input-Sache wechseln, wenn ich etwas Zeit dafür finde. Eine wirklich nette Antwort. –

+0

BTW eine seltsame Sache ist, dass AutoHotkey davon nicht betroffen ist. –

+1

AutoHotKey ist open-source, lesen Sie den Quellcode (https://github.com/Lexikos/AutoHotkey_L), um zu sehen, wie es damit umgeht. –