3

私は、最初のプログラムから生成されたすべての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が必要になることを理解しています。

4

1 に答える 1

2

同様の問題が発生した場合の最終的な解決策は、生成されGetWindowThreadProcessId(GetForegroundWindow(), ref foregroundWindowProcessId)たプロセス ID のマップを使用して一定間隔でフォアグラウンド ウィンドウをチェックすることでした。このタイマーが起動するたびに、呼び出す関数をチェックインするためのブール値を設定しますCallNextHookEx。これは、関数が効率的/高速である必要があるか、ウィンドウがフックを解除するためです。次に、上記のブール値とシステム フックを使用してSetWindowsHookEx、ユーザーがアプリケーションでアクティブかどうかを判断します。このソリューションには C++ dll は必要ありませんでした。

于 2015-08-27T15:18:23.890 に答える