私は、最初のプログラムから生成されたすべてのGUIプログラムのアクティビティを監視し、設定された期間非アクティブになったときにそれらを強制終了するという任務を負っています。ユーザーが(最初のプログラムによって生成されたのではなく)しばらくの間別のプログラムを使用している場合でも、プログラムを閉じる必要があるため、これはシステムアクティビティではありません。アプリケーションの生成プロセスは.Netプログラムであり、変更されることはありません。SetWindowsHookEx
.Netから低レベルのフック(WH_KEYBOARD_LL
および)を設定するために使用できましWH_MOUSE_LL
たが、メッセージを開始したプロセスに関連付ける方法がわかりませんでした(を使用してSystem.Diagnostics.Process
)。フックを実行するアプリケーションからイベントをフックすることはできましたが、生成されたプログラムの特定のスレッドにフックしようとすると、常に失敗します。
SetWindowsHookEx
私が到達できた最も近い方法は、.Netプログラムに代わって呼び出すC++dllを作成することでした。このメソッドを使用すると、生成されたnotepad.exeの最初のスレッドにフックできますが、コールバック関数が呼び出されることはありません。SetWindowsHookEx
スレッドIDを0に指定すると、元のアプリケーションにアクティビティがあるときにコールバックが呼び出されるため、その場合の動作がわかります。
私はまだフックを完全には理解していませんが、dllコールバック関数のアドレスはフックされたプロセスにとって無意味であるため、私が読んだことからこれは機能しません。それは私が直面している問題ですか?もしそうなら、これを回避する方法はありますか、または誰かがスポーンされたプロセスがアクティブに使用されているかどうかを判断するための代替案を提案できますか?
.Net(C#)コード:
private const int WH_MOUSE = 14;
[DllImport("TestHook.dll", EntryPoint="InitializeHook", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern bool InitializeHook(uint hookType, int threadID);
private void HookEm() {
//...
System.Diagnostics.Process testProcess = System.Diagnostics.Process.Start("notepad");
if(!InitializeHook(WH_MOUSE, testProcess.Threads[0].Id)) // The notepad.exe thread I know hooks
MessageBox.Show("Boom!");
//...
}
C ++ dll:
HHOOK hookValue;
bool InitializeHook(UINT hookID, int threadID) {
//... Determining which callback to use
hookValue = SetWindowsHookEx(hookID, (HOOKPROC)MouseHookCallback, _dllInstance, threadID);
//...
return hookValue != NULL
}
static LRESULT CALLBACK MouseHookCallback(int code, WPARAM wparam, LPARAM lparam) {
//From what I can see, this is never touched when hooking a thread on an outside process
}
これらはすべて、現在32ビットのWindowsXPコンピュータで実行されています。生成された64ビットアプリケーションを処理するには、別の64ビットdllが必要になることを理解しています。