1

JNIを使​​用して単純な低レベルのキーフックを実装しようとしましたが、DLLが無限ループ(メッセージループ)にある間はメソッドを呼び出すことができないと考えるまで、すべてうまくいきました。だから私は新しいスレッドを作成することにしましたが、どういうわけか、メッセージループが独自のループで実行されるように作成した後、低レベルのキーフックが応答を停止し、keyproc をもう呼び出さないことを意味します。これに対する他の回避策はありますか?キーボード フックがまだ機能している間に、DLL のメソッドを呼び出せるようにする必要があります。

私の現在のコードは次のように単純です

キーボードフックの登録:

keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProc, hInstance, 0);

スレッドを開始

HANDLE threadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &threadId);

私のキーボード proc と threadproc は次のとおりです。

DWORD WINAPI ThreadProc(LPVOID lpVoid) {
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK keyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    KBDLLHOOKSTRUCT keyEvent = *((KBDLLHOOKSTRUCT*)lParam);
    jint vkCode = keyEvent.vkCode;
    jint flags = keyEvent.flags;
    jint action = wParam;
    (*globalEnv).CallVoidMethod(globalObj, keyboardMethodId, vkCode, flags, action);
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

どこで間違っていますか?keyproc の単純なロギングを追加しても、決して呼び出されないので、Java ではないことは確かです。しかし、スレッドの使用をやめてメイン スレッドでメッセージ ループを実行すると、正常に動作しますが、DLL はその後のメソッド呼び出しに応答しません。

4

2 に答える 2

3

SetWindowsHookEx() を呼び出したのと同じスレッドでメッセージ ループをポンピングする必要があります。そのため、呼び出しを ThreadProc() に移動するだけです。そしてもちろん、 CallVoidMethod() コールバックも同じスレッドで実行されることに注意してください。そのため、その関数で何をするかに注意してください。アクセスするすべての共有状態は、ロックで保護する必要があります。

于 2012-04-06T15:09:25.247 に答える
2

デスクトップのすべてのプロセスにまたがるデスクトップ全体のフックをインストールしようとしています。つまり、DLL は、プロセス固有のグローバル変数セットを使用して複数のプロセスにマップされます。他のプロセスで有効になっておらずglobalEnv、アクセス違反や同様のエラーが発生する可能性があります (グローバル変数は共有データ セグメントで作成できます。詳細については、この記事を参照してください)。

スレッド固有のフックをインストールするには、別のタイプのフック (WH_KEYBOARD_LLグローバルのみです!) と のゼロ以外の最後の引数が必要SetWindowsHookExです。

于 2012-04-06T15:04:33.393 に答える