1

主観…は

わかりましたので、複数のキーストロークをトラップするための合理的な解決策をインターネットで探していて、同じもの(キーボードフック)を使用するいくつかの解決策に出くわしました。1 つのソリューションではネイティブ コールを使用してプロセスの IntPtr を名前で取得し、もう 1 つのソリューションでは LoadLibrary("User32.dll") を使用しました。

だから私は「賢い」と思ってこれをやった(成功した)

IntPtr hInstance = Process.GetCurrentProcess().MainModule.BaseAddress;
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);

これを使用するのと同じように

IntPtr hInstance = LoadLibrary("User32.dll");
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);

一方は他方より安全ですか?頭を見せていない致命的なエラーを犯していますか?

4

2 に答える 2

3

SetWindowsHookEx() には、有効なモジュール ハンドルが必要です。これを使用して、フックを機能させるために他のプロセスに挿入する必要がある DLL を特定します。

しかし、それはグローバル フックの要件にすぎません。2 つの低レベル フック (WH_MOUSE_LL と WM_KEYBOARD_LL) は特殊で、DLL インジェクションを必要としません。Windows は、独自のプロセスでのみフック コールバックを呼び出します。唯一の要件は、Windows がコールバックできるように、スレッドがメッセージ ループをポンピングすることです。Application.Run() が必要です。

また、低レベルのフックを C# で機能させることができる理由として、グローバル フックで使用される DLL をマネージ言語で記述することはできません。これは、挿入されたプロセスに CLR が読み込まれないためです。

奇妙な点は、SetWindowsHookEx() は、有効なモジュール ハンドルを渡したかどうかをチェックしますが、実際にはそれを低レベルのフックに使用しないことです。したがって、渡した有効なハンドルはすべて機能します。この癖は Windows 7 SP1 で修正されましたが、そのチェックは実行されなくなりました。

于 2013-01-10T15:12:54.377 に答える
0

編集:私の最初の回答では、IntPtr.Zeroオプションを開いたままにし、決定に役立つ必要な情報を提供しました。docsから別の引用を追加しています。これは、null を使用しない場合について説明しています。

hMod パラメータが NULL で、dwThreadId パラメータがゼロであるか、別のプロセスによって作成されたスレッドの識別子を指定している場合、エラーが発生する可能性があります。

スレッド ID として 0 を使用しているため (ドキュメントによると、「呼び出し元のスレッドと同じデスクトップで実行されているすべての既存のスレッド」を意味します)、null ではなくMarshal.GetHINSTANCEを使用する必要があります。


IntPtr.Zero またはMarshal.GetHINSTANCE(your current module)

これらのドキュメントによると、3 番目の引数 ( hMod) は -

lpfn パラメータが指すフック プロシージャを含む DLL へのハンドル。dwThreadId パラメータが現在のプロセスによって作成されたスレッドを指定し、フック プロシージャが現在のプロセスに関連付けられたコード内にある場合は、hMod パラメータを NULL に設定する必要があります。

また、この記事 (「.NET Framework の Windows フック」) で説明されているように

3 番目の引数は、フィルター関数のコードを含む DLL の HINSTANCE ハンドルである必要があります。通常、ローカル フックの場合、この値は NULL に設定されます。ただし、.NET null オブジェクトは使用しないでください。Win32 null ハンドルの正しい対応物である IntPtr.Zero 式を使用します。システム全体のフックの HINSTANCE 引数を null にすることはできませんが、フック コード (通常はアセンブリ) を含むモジュールに関連付ける必要があります。Marshal.GetHINSTANCE 静的メソッドは、指定された .NET モジュールの HINSTANCE を返します。

また、この質問を参照してください。

于 2013-01-10T15:15:18.167 に答える