【问题标题】:SetWindowsHookEx(WH_KEYBOARD) not working with thread IDSetWindowsHookEx(WH_KEYBOARD) 不适用于线程 ID
【发布时间】:2014-02-05 12:03:46
【问题描述】:

我有一个被进程调用的 dll,现在我想在 dll 中实现输入检查,以对应用程序中出现的某些输入做出反应。

带有KeyboardProc 函数的SetWindowsHookEx() 似乎是一个可行的解决方案,所以我实现了它。

dll中的代码大致是这样的:

static HHOOK hhk = NULL;
LRESULT CALLBACK keyboardProc(int code, WPARAM wParam, LPARAM lParam)
{  
    if(code == HC_ACTION && ((DWORD)lParam & 0x80000000) == 0)  // if there is an incoming action and a key was pressed
    {
       switch(wParam)
       {
       case VK_SPACE:
          printf("Space was pressed\n");
          break;
       }
    }
    return CallNextHookEx(hhk, code, wParam, lParam);
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    if(ul_reason_for_call == DLL_PROCESS_ATTACH)
    {
        if(AllocConsole()){
            freopen("CONOUT$", "w", stdout);  // redirect output to console for debugging
        }
        printf("Dll loaded, lastError = %i\n", GetLastError());
        printf("lastError = %i\n", GetLastError());
        // sidenote: for some reason the first GetLastError() returns 0 while the second one returns 6 (invalid handle)

        hhk = SetWindowsHookEx(WH_KEYBOARD, keyboardProc, hModule, GetCurrentThreadId());
    }
    else if (ul_reason_for_call == DLL_PROCESS_DETACH)
    {
        printf("\nCleaning up...");
        FreeConsole();
        UnhookWindowsHookEx(hhk);
    }
    return TRUE;
}

但是,当我按任意键时,控制台窗口中什么也没有发生(或打印)。 keyboardProc 函数似乎在任何时候都无法访问。

当我将NULL 而不是GetCurrentThreadId() 传递给SetWindowsHookEx() 时,它确实 起作用。 但这会导致钩子在全局范围内工作,这意味着每当我在另一个应用程序中按下一个键时,就会弹出一个控制台窗口(因为再次调用了 dll)并且他在那里检查键输入。 显然这是不希望的,我想只使用最初调用 dll 的进程。

我已经检查了GetCurrentThreadId() 是否返回了一个有效的 ID,并且它似乎确实是最初调用 dll 的进程的主线程 ID(使用 Process Explorer 检查)。

所以现在我的问题是可能是什么问题,更重要的是,我该怎么做才能使它正常工作?

【问题讨论】:

  • 程序默认调用 DLL。但是我没有程序的源代码,只有 DLL。如果线程 ID 正确,我已经多次使用 Process Explorer 检查过,并且还尝试使用此 sn-p -> codeproject.com/Questions/78801/… 通过进程 ID 加载它
  • 你解决这个问题了吗?我遇到了完全相同的问题:(
  • 很遗憾没有,任何建议仍然非常感谢(抱歉迟到的回复)。
  • 我相信您应该在您的应用程序中包含一个消息循环才能使其正常工作。 while (GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg);调度消息(&msg); }

标签: c++ windows dll hook


【解决方案1】:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

uint process_id;
uint thread_id = GetWindowThreadProcessId(windowHandle, out process_id);
hhook = SetWindowsHookEx(WH_KEYBOARD, a_KeyboardProc, hInstance, 0);

我已经使用上面的代码来获取某个进程的主线程 ID。好的部分是,SetWindowsHookEx 函数给出了一个逻辑输出。不幸的是,如果在已经钩住的线程中按下一个键,线程就会停止工作。

在我的例子中,对于非低级键盘事件,SetWindowsHoookEx 函数的 idHook 参数设置为 2(而不是 13)。至少在我看来,LL 对应于低级,其中 keyboardProc 应该带有 WH_KEYBOARD 而不是 WH_KEYBOARD_LL。

目前我不确定我的回答与您的问题有何关联。希望我们通过讨论得到我们需要的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多