キーボードフックを使用するプログラムに取り組んでいます。ただし、プログラムが実行されているPCがわずかに過負荷になると、Windowsがプログラムからフックを切断し、キーストロークに応答しなくなります。
これを防ぐ方法、またはさらに良い方法として、パイプラインを含む別のアーキテクチャを使用して、まったく同じ問題を解決する別の方法を提案する方法はありますか?
キーボードフックを使用するプログラムに取り組んでいます。ただし、プログラムが実行されているPCがわずかに過負荷になると、Windowsがプログラムからフックを切断し、キーストロークに応答しなくなります。
これを防ぐ方法、またはさらに良い方法として、パイプラインを含む別のアーキテクチャを使用して、まったく同じ問題を解決する別の方法を提案する方法はありますか?
これを「検出」することはできません。絶対に検出する必要はありません。説明しているのは機能です。具体的には、不正なアプリケーションからシステムを保護するためにWindows7で導入された機能です。
該当するドキュメントでは、このように説明されています(太字のセクションに特に注意してください)。
フックプロシージャは
LowLevelHooksTimeout
、次のレジストリキーの値で指定されたデータエントリよりも短い時間でメッセージを処理する必要があります。HKEY_CURRENT_USER\Control Panel\Desktop
値はミリ秒単位です。フック手順がタイムアウトした場合、システムはメッセージを次のフックに渡します。ただし、Windows 7以降では、フックは呼び出されずにサイレントに削除されます。フックが取り外されているかどうかをアプリケーションが知る方法はありません。
ここでの解決策は、フックがアンインストールされて再インストールされたときに「検出」する方法を見つけ出さないことです。オペレーティングシステムが最初にフックをアンインストールしたときに、何か問題が発生していることを理解しておく必要があります。
実際の解決策は、フック手順からより迅速に戻るようにアプリケーションを再設計することです。理想的には、ほとんどすぐに戻る必要があります。低レベルのメッセージに応答してある種の集中的な計算を実行する必要がある場合(そしてなぜそうするのか私には想像できません)、受け取った情報を保存し、フックプロシージャから戻って、次の場所で処理を行う必要があります。後で(おそらく別のスレッドで)。
実際、それはドキュメントが示唆し続けていることとほぼ同じです。
注: デバッグフックは、このタイプの低レベルキーボードフックを追跡できません。アプリケーションが低レベルのフックを使用する必要がある場合は、作業をワーカースレッドに渡し、すぐに戻る専用スレッドでフックを実行する必要があります。アプリケーションが低レベルのフックを使用する必要があるほとんどの場合、代わりに生の入力を監視する必要があります。これは、raw入力が、低レベルのフックよりも効果的に他のスレッドを対象とするマウスとキーボードのメッセージを非同期的に監視できるためです。生の入力の詳細については、生の入力を参照してください。
キーボードのフックが常に原因であるかどうかはわかりません。私たちは皆、理想的または平均的な条件下では、すべてが応答する必要があることに同意しているようです。しかし、起動からシャットダウンまでの存続期間中、フックはいくつかの最悪のシナリオにも耐えなければなりません。私の会社では、いくつかのキーボードフックを作成しました。それらは可能な限り軽量で非同期ですが、それでも時々切断されているように見えます。
ユーザーとして、私は毎日数万文字を入力します。私はせいぜい月に1回再起動しますが、WindowsUpdateをスキップしたことで罪を犯すこともあります。サスペンドやハイバネートなどのオプションがあるので、私は一人ではないと思います。開発者として、システムに何が起こっても、フックが最初から最後まで実行され続けることを確認する必要があります。
通常、私のシステムは非常に反応が良いです。しかし、Windows Aeroでさえもオフになるまで、ひざまずいて例外的な瞬間が発生する可能性があります。今はとてもきびきびしています。しかし、[デスクトップの表示]ボタンを押すと、65ほど開いているウィンドウがすべて折りたたまれている間、マウスが少なくとも1秒間フリーズします。これらの瞬間のいずれかでキーを押すとどうなりますか?
Windowsがマウスを1秒間フリーズできる場合、Windowsが重い負荷の短い瞬間にAeroをオフにすることさえできる場合、キーボードフックが同様の例外的な過負荷の時間に耐えることができないのはなぜですか?代わりに、1つの例外的な瞬間のために、Windowsはプラグを抜き、システムがシャットダウンするまで残りのコンピューティングエクスペリエンスにサイレントに影響を与えます。毎日押す数千回のうち1回のキー押下に影響を与える200ミリ秒の間、ユーザーである私は、システムを再起動する必要があります。これが、キーボードマクロやその他のユーティリティを復活させる唯一の方法であると理解しているためです。私は自分の生産的な仕事を頼りにしています。
上記を防ぐことが保証されていたとしても(最悪の場合の経験ではそうではないようです)、すべてが別のスレッドで簡単に実行できるかどうかはわかりません。たとえば、ユーザーがアプリケーションを起動するためのホットキーを設定するとします。現在のコンテキスト(フォアグラウンドウィンドウ、特権など)からアプリケーションを起動する理由はありませんか?そして、ユーザーが実際に遅延を予想して受け入れるのは合理的ではないでしょうか。なぜなら、彼はキーボードを使用して、もっと時間がかかる何かを始めたばかりであることを知っているからです。例が技術的に適切かどうかはわかりませんが、既知のイベントの結果として、他の方法では受け入れられない可能性のあるものがどのように受け入れられるかを説明したいと思いました。
キーボードフックは、マクロからエラー修正、起動まで、多くのことに非常に役立ちます。Windows7で導入されたこの動作により、良い点と悪い点、許容できる値と許容できない値、平均的な値と例外的な値がすべて同じになります。バスケット。高品質のキーボードフックが殺される可能性があるため、これは両方のユーザーと開発者を傷つけます。通常の条件下ではアプリケーションが正常に機能しているが、高負荷(またはその他の不可解な)状況下でランダムに強制終了されるという公式の解決策がない場合のサポートの悪夢を想像してみてください。
質問でこれを結論付けるために、誰かがWindows 8でのステータスが何であるかを知っていますか?何か変更がありますか?
Cody Greyの応答は優れていますが、FWIWであり、純粋にテスト目的で、切断されたフックを検出できる場合があります。
フックプロシージャが呼び出されたら、現在のティックカウントをメインスレッドにアクセス可能な変数に格納します。メインスレッドで、定期的にを呼び出しますGetLastInputInfo
。これにより、システム内の最後の入力イベント(プロセス内だけでなく)のティックカウントがわかります。によって提供される値がGetLastInputInfo
、最後のフックprocティックカウントよりも大幅に遅い(新しい)場合は、フックが切断されていると考えられます。
私はあなたのフックにいくつかの「パフォーマンスの悪い」コードがあると思います。それがわずかに過負荷になる理由です。
「これにより、Windowsはプログラムからフックを切断します」
フックにエラーが発生し、それを処理しませんか?
ちなみに、Windowsは、それ自体がうまく機能していれば、フックを切断しません。
アプリケーションのプロセスの優先度を上げてみてください。