24

SetWindowsHookExwithを介してインストールされたいくつかのグローバル キーボード フックWH_KEYBOARD_LLがあり、Windows によってランダムにフック解除されるようです。

UnhookWindowsHookExハンドルを呼び出すと が返されるため、フックがアタッチされなくなったことを確認しましたfalsetrue(正常に動いていた時に戻ることも確認済み)

一貫した再現性はないようです。タイムアウトや例外がスローされたためにフックが外れる可能性があると聞きましたが、処理メソッドのブレークポイントに1分以上置くだけで両方を試しました.ランダムな例外 (C#) をスローするだけでなく、それでも動作しているように見えます。

コールバックでは、すぐに別のスレッドに投稿するので、おそらく問題にはなりません。Windows 7は明らかにタイムアウトについてより積極的であるため、レジストリでタイムアウトをより高く設定するためのWindows 7のソリューションについて読みました(ここではすべてWin7を実行しているため、これが他のOSで発生するかどうかはわかりません)が、そうではありません理想的な解決策とは思えません。

バックグラウンド スレッドを実行してフックを時々更新することを検討しましたが、これはハックですが、それを行うことによる実際の悪影響については知りません。Windows のグローバル レジストリ設定を変更するよりも優れているようです。 .

他の提案や解決策はありますか? フックを設定するクラスとそれらがアタッチされているデリゲートはどちらも静的であるため、GC を取得するべきではありません。

編集:GC.Collect();それらがまだ機能していることを呼び出して検証したため、ガベージ収集されていません。

4

7 に答える 7

18

これはタイムアウトの問題である必要があると思います。

他の開発者は、(文書化されていない)タイムアウト値を超えると低レベルのフックがフック解除されるというWindows7固有の問題を報告しています。

同じ問題について議論している他の開発者については、このスレッドを参照してください。フックを解除する動作を引き起こすには、スリープではなくビジーループ(または低速のガベージコレクション)を実行する必要がある可能性があります。LowLevelKeyboardProc関数のブレークポイントも、タイムアウトの問題を引き起こす可能性があります。(別のタスクによるCPU負荷が大きいと、動作が引き起こされる可能性があるという観察結果もあります。おそらく、他のタスクがLowLevelKeyboardProc関数からCPUサイクルを盗み、時間がかかりすぎるためです。)

そのスレッドで提案されている解決策は、HKEY_CURRENT_USER \ Control Panel\DesktopのレジストリにあるLowLevelHooksTimeoutDWORD値をより大きな値に設定してみることです。

C#の栄光の1つは、ガベージコレクションが発生した場合、単純なステートメントでも非常に長い時間がかかる可能性があることです。これ(または他のスレッドによるCPUのロード)は、問題の断続的な性質を説明している可能性があります。

于 2010-04-21T03:46:38.163 に答える
3

問題がどこにあるかを理解するのに役立つ可能性があると私が考えたことが2つあります。

  1. 問題の場所を特定するにはWH_KEYBOARD_LL、現在のフックと同時に別のフックを実行し、フック チェーンに沿ってデータを渡す以外に何も行わないようにします。元のフックが外れていることがわかったら、この「ダミー」フックも外れていないか確認してください。「ダミー」フックもアンフックされている場合、問題がフックの外にあることはほぼ確実です (つまり、Windows またはプロセス全体に関連するものでしょうか?) 「ダミー」フックがアンフックされていない場合、問題はおそらくあなたのフックのどこかにあります。

  2. コールバックを介してフックに来る情報をログに記録し、フックがアンフックされるまで実行します。これを何度も繰り返し、ログに記録されたデータを調べて、フックが外れるまでのパターンを識別できるかどうかを確認します。

いずれかが他の結果に影響を与える場合に備えて、これらを一度に1つずつ試します. その後、問題が何であるかの手がかりが得られない場合は、それらを一緒に実行してみてください。

于 2010-04-20T20:26:14.117 に答える
2

長い道のりですが、万が一、ウイルス対策ソフトウェアを実行していますか?それは、キーボードのフックに気づき、それを蹴り出すことである可能性が非常に高いです。

警告が表示され、すぐに削除される可能性が高くなりますが、確認する価値のある奇妙なことの1つです。

于 2010-04-26T03:23:45.897 に答える
1

おそらく他の誰かがCallNextHookEx()を呼び出していないフックを持っていますか?

于 2010-04-21T03:47:51.307 に答える
1

http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-Cの次のプロジェクトを使用して、特定のキーが押されたときにタスクを実行します。

ホットキーを使用してタスクを実行した後、新しいキープレスのリッスンを停止したことに気付きました。その後、KeyboardHookListener を static に変更すると、問題が解決したようです。これで問題が解決した理由がわからないので、お気軽にコメントしてください。

私のホットキークラス:

 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();
        }
    }
}
于 2014-04-06T16:09:10.267 に答える
1

私はそれが醜い解決策であることを知っていますが、タイマーを5分間設定してから、キーボードイベントを再フックできますか?

私はWin7マシンで同じ問題を抱えていました。しばらくすると、キーボードフックが参照を失い、イベントを再びフックするために5分ごとにタイマーを設定する必要がありましたが、今では新鮮に保たれています。

于 2013-06-27T18:54:09.753 に答える