Frage

Wir haben einige globale Tastaturhaken über SetWindowsHookEx mit WH_KEYBOARD_LL installiert, die zufällig von Windows-get ausgehängt erscheinen.

Wir Nachweis erbracht, dass sie Haken war nicht mehr angebracht, weil UnhookWindowsHookEx auf dem false Griff wieder aufrufen. (Auch bestätigt, dass es true zurückgibt, wenn es funktionierte einwandfrei)

Es scheint nicht, eine konsistente Repro zu sein, ich habe gehört, dass sie aufgrund von Timeouts oder Ausnahmen bekommen hakte können geworfen zu werden, aber ich habe versucht, beide läßt es einfach auf einem Haltepunkt in der Handhabung Methode sitzt über eine Minute, als auch nur eine zufällige Ausnahme (C #) zu werfen und es scheint, noch zu arbeiten.

In unserem Rückruf veröffentlichen wir schnell auf einem anderen Thread, so dass wahrscheinlich nicht das Problem ist. Ich habe über Lösungen in Windows 7 zum Einstellen des Timeout höher in der Registrierung gelesen, weil Windows 7 offenbar aggressiver über den Timeouts ist (wir sind all Win7 hier laufen, also nicht sicher, ob dies auf anderen Betriebssystemen auftritt), aber das doesn ‚t scheinen, wie eine ideale Lösung.

habe ich als nur einen Hintergrund-Thread mit Lauf den Haken zu aktualisieren jeder einmal in eine Weile, die hackish ist, aber ich weiß nicht von irgendwelchen realen negativen Folgen, das zu tun, und es scheint besser als eine globale Veränderung Windows-Registry-Einstellung.

Alle anderen Vorschläge oder Lösungen? Sowohl die Klasse, die Sätze die Haken und die Delegierten sie gebunden sind, zu statisch sind, so sollten sie nicht GC'd bekommen.

EDIT:. Verifiziert mit Aufrufen an GC.Collect();, dass sie noch arbeiten, so dass sie nicht garbaged gesammelt zu werden

War es hilfreich?

Lösung

Ich denke, das ein Timeout Problem sein muss.

Andere Entwickler haben eine Windows7 spezifisches Problem mit geringen Haken ausgehängt werden berichtet, wenn sie einen (undokumentiert) Timeout-Wert nicht überschreiten.

Siehe dieses Thema für andere Entwickler das gleiche Problem zu diskutieren. Es kann sein, dass Sie einen vollen Schleife ausführen müssen (oder eine langsame Garbage Collection) eher als ein Schlaf das Aushängen Verhalten zu verursachen. Ein Haltepunkt in der LowLevelKeyboardProc Funktion könnte auch Timeout Probleme verursachen. (Es gibt auch die Beobachtung, dass eine schwere CPU-Last durch eine andere Aufgabe könnte das Verhalten provozieren -. Vermutlich, weil die andere Aufgabe CPU-Zyklen von der LowLevelKeyboardProc Funktion stiehlt und bewirkt, dass es zu lange dauern)

Die Lösung in diesem Thread vorgeschlagen ist, die , um zu versuchen Einstellung LowLevelHooksTimeout DWORD-Wert in der Registrierung auf HKEY_CURRENT_USER \ Control Panel \ Desktop auf einen höheren Wert.

Beachten Sie, dass eine der Herrlichkeiten von C # ist, dass selbst einfache Aussagen unmäßig viel Zeit in Anspruch nehmen können, wenn eine Garbage Collection auftritt .. Diese (oder CPU-Belastung durch andere Threads) könnte die intermittierende Natur des Problems erklären.

Andere Tipps

Es gibt zwei Dinge, die ich von dieser helfen könnte gedacht haben Sie herausfinden, wo das Problem ist.

  1. , um das Problem der Lage zu isolieren, führen Sie einen anderen WH_KEYBOARD_LL Haken gleichzeitig mit Ihrem aktuellen Haken und haben es nichts anderes als die Daten auf der ganzen Haken Kette passieren. Wenn Sie feststellen, dass Ihr ursprünglicher Haken Unhooked ist, prüfen und sehen, ob dieser „Dummy“ Haken auch ausgehängt wurde. Wenn der „Dummy“ Haken auch ausgehängt wurde, können Sie ziemlich sicher sein, das Problem außerhalb des Hakens (dh in Windows oder etwas im Zusammenhang mit Ihrem Prozess als Ganze?) Wenn der „Dummy“ Haken nicht ausgehängt wurde, dann ist das Problem wahrscheinlich irgendwo in Ihrem Haken ist.

  2. Protokoll der Informationen, die über den Rückruf an den Haken kommt, und führen Sie es, bis der Haken ausgehängt wird. Wiederholen Sie diesen Vorgang mehrmals und prüfen die Daten protokolliert, um zu sehen, wenn Sie ein Muster führt bis zum Aushängen erkennen kann.

Ich würde diese einen nach dem anderen versuchen, nur für den Fall entweder würde die anderen Ergebnis beeinflussen. Wenn nach, dass Sie haben keine Leitungen auf, was das Problem sein könnte, könnte man versuchen, sie zusammen ausgeführt werden.

Es ist ein langer Schuss, aber durch Zufall hast du Anti-Virus-Software läuft? Das könnte sehr gut eine Tastatur Haken werden bemerken, und treten Sie es heraus.

Es ist wahrscheinlicher, würde es Sie warnen, und entfernen Sie es sofort, aber es ist eine jener seltsame Dinge wert.

Vielleicht hat jemand anderes einen Haken, der nicht CallNextHookEx Aufruf wird ()?

Ich weiß, es ist eine hässliche Lösung, aber Sie einen Timer für je 5 Minuten eingestellt, dann können Sie Ihre Tastaturen Ereignisse wieder einhaken?

Ich hatte ein gleiches Problem mit Win7 Maschine, nach einer Weile Tastatur Haken waren es die Referenz zu verlieren, und ich hatte einen Timer für alle 5 Minuten einzurichten Ereignisse Haken wieder, und jetzt hält es frisch.

Ich bin mit dem folgende Projekt aus: http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C Aufgaben auszuführen, wenn eine bestimmte Taste gedrückt wurde.

Ich habe bemerkt, dass, nachdem ich eine Aufgabe mit einem Hotkey ausgeführt es für neue Tastenfolgen hörte nicht mehr zu, ich dann die KeyboardHookListener zu statisch geändert und es schien, mein Problem zu lösen. Ich habe keine Ahnung, warum das mein Problem gelöst, so fühlen sich frei, um Kommentar zu diesem!

Meine Hotkey-Klasse:

 class Hotkey
{
    private static KeyboardHookListener _keyboardHookListener;

    public void Start()
    {
        _keyboardHookListener = new KeyboardHookListener(new GlobalHooker()) { Enabled = true };
        _keyboardHookListener.KeyDown += KeyboardListener_OnkeyPress;
    }

    private void KeyboardListener_OnkeyPress(object sender, KeyEventArgs e)
    {
        // Let's backup all projects
        if (e.KeyCode == Keys.F1)
        {
            // Initialize files
            var files = new Files();

            // Backup all projects
            files.BackupAllProjects();
        }
        // Quick backup - one project
        else if (e.KeyCode == Keys.F2)
        {
            var quickBackupForm = new QuickBackup();
            quickBackupForm.Show();
        }
    }
}

Sehr spät, aber dachte, ich würde etwas teilen. Das Sammeln von hier es gibt ein paar Hinweise, wie die SetWindowsHookEx in einem separaten Thread setzen und dass es mehr ein Planungsproblem.

Ich habe auch bemerkt, dass Application.DoEvents wurde mit ziemlich viel CPU, und festgestellt, dass PeekMessage weniger verwendet.

public static bool active = true;

[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
    public IntPtr handle;
    public uint msg;
    public IntPtr wParam;
    public IntPtr lParam;
    public uint time;
    public System.Drawing.Point p;
}

[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool PeekMessage(out NativeMessage message,
    IntPtr handle, uint filterMin, uint filterMax, uint flags);
public const int PM_NOREMOVE = 0;
public const int PM_REMOVE = 0x0001;

protected void MouseHooker()
{
    NativeMessage msg;

    using (Process curProcess = Process.GetCurrentProcess())
    {
        using (ProcessModule curModule = curProcess.MainModule)
        {
            // Install the low level mouse hook that will put events into _mouseEvents
            _hookproc = MouseHookCallback;
            _hookId = User32.SetWindowsHookEx(WH.WH_MOUSE_LL, _hookproc, Kernel32.GetModuleHandle(curModule.ModuleName), 0);
        }
    }
        while (active)
        {
            while (PeekMessage(out msg, IntPtr.Zero,
                (uint)WM.WM_MOUSEFIRST, (uint)WM.WM_MOUSELAST, PM_NOREMOVE))
                ;
            Thread.Sleep(10);
        }

        User32.UnhookWindowsHookEx(_hookId);
        _hookId = IntPtr.Zero;            
}

public void HookMouse()
{
    active = true;
    if (_hookId == IntPtr.Zero)
    {
        _mouseHookThread = new Thread(MouseHooker);
        _mouseHookThread.IsBackground = true;
        _mouseHookThread.Priority = ThreadPriority.Highest;
        _mouseHookThread.Start();
    }
}

so ändern, nur die aktive Bool auf false in Deactivate-Ereignisse und ruft HookMouse im Activated-Ereignisse.

HTH

EDIT: Ich habe bemerkt, Spiele wurden mit diesem verlangsamt, so beschlossen, aushängen, wenn App nicht aktiv ist mit Aktivierte und deaktivieren Ereignisse

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