设置 WH_KEYBOARD 挂钩失败并出现错误 1428

Lon*_*ner 2 c++ winapi visual-studio

这是我的 C++ 代码:

#include <iostream>
#include <windows.h>

HHOOK hook;

LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
    std::cout << "Hook callback" << std::endl;
    return CallNextHookEx(hook, nCode, wParam, lParam);
}

int main(int argc, char **argv)
{
    hook = SetWindowsHookEx(WH_KEYBOARD, keyboardHook, NULL, NULL);
    if (hook == NULL) {
        std::cout << "Error " << GetLastError() << std::endl;
        return 1;
    }
    std::cout << "Hook set" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我使用 Visual Studio 编译它,如下所示:

cl /D_WIN32_WINNT=0x0401 foo.cc /link user32.lib
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我收到错误 1428。

C:\>foo.exe
Error 1428
Run Code Online (Sandbox Code Playgroud)

这就是错误1428的含义。

C:\nocaps>net helpmsg 1428

Cannot set nonlocal hook without a module handle.
Run Code Online (Sandbox Code Playgroud)

您能帮我理解这个错误并使这段代码正常工作吗?如果您能为我提供一个可以工作并调用回调的工作代码,那就太好了?

我发现如果我使用 WH_KEYBOARD_LL 钩子代替,它工作得很好。但我需要了解如何使 WH_KEYBOARD 挂钩发挥作用。

man*_*ell 5

WH_KEYBOARD_LL挂钩始终在安装挂钩的线程上下文中运行。钩子函数不需要位于 DLL 中,并且钩子可以捕获来自应用程序的事件,无论其位数如何。技巧是:操作系统对线程消息队列执行某种特殊的“SendMessage”。这就是为什么您必须在挂钩线程中安装活动消息循环的原因。

WH_KEYBOARD钩子可以在安装钩子的线程的上下文中运行。这意味着它们也可以在挂钩线程的上下文中运行。这会强加一个位于 DLL 中的钩子函数。我相信(但不确定)如果位数相同,挂钩函数将“就地”执行(在挂钩线程的上下文中),并且位数不匹配的回退依赖于所使用的相同技术对于 WH_KEYBOARD_LL。这意味着您还必须在挂钩线程中安装活动消息循环(如果不这样做,您将错过来自具有其他位的应用程序的所有事件)

注意:在被钩子线程的上下文中执行的钩子函数会使所有内容变得cout << "Hello\n"毫无用处。您必须使用文件(或 IPC)。