【问题标题】:Global Keyboard hook not working全局键盘挂钩不起作用
【发布时间】:2010-01-24 12:59:27
【问题描述】:

我创建了一个全局键盘挂钩。

钩子是在 DLL 中创建的。

#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
static HHOOK hkb=NULL;
static CMyFile *pLF;
#pragma data_seg()

HINSTANCE hins = NULL;

extern "C"
LRESULT  __declspec(dllexport) __stdcall  CALLBACK KeyBoardHookProc(
    int nCode, 
    WPARAM wParam, 
    LPARAM lParam)
{

if (nCode < 0) {
        return CallNextHookEx(0, nCode, wParam, lParam);
    }

    return CallNextHookEx(hkb, nCode, wParam, lParam);
}

extern "C"
LRESULT __declspec(dllexport) __stdcall CALLBACK Install()
{
    pLF = new CMyFile(L"c:\\1.txt");
    hkb = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyBoardHookProc,hins,0);
    return 0;

}

extern "C"
BOOL __declspec(dllexport) __stdcall CALLBACK UnInstall()
{
    return UnhookWindowsHookEx(hkb);
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{

    switch(ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH :
        hins = (HINSTANCE) hModule;
        break;

    case DLL_THREAD_ATTACH :
        break;

    case DLL_THREAD_DETACH :
        break;

    case DLL_PROCESS_DETACH :
        break;
    }
    return TRUE;
}

我已经创建了一个加载这个 dll 并调用钩子 dll 的安装函数的 EXe。

 HMODULE hMod = LoadLibrary(L"hk.dll");
   if(hMod!=NULL)
   {
       typedef LRESULT (__stdcall CALLBACK *_installhk)() ;
       _installhk installProc;
       installProc = (_installhk) GetProcAddress(hMod,"Install");
       if(installProc!=NULL)
       {
           installProc();
       }
   }

当我启动 exe 时,KeyBoardHookProc 上的调试断点只被命中一次。

除非我关闭它,否则 exe 会继续运行,但如果我从键盘输入任何其他内容,则不会调用挂钩过程。

这可能是什么原因?

这不是设置全局键盘挂钩的正确方法吗?

【问题讨论】:

    标签: c++ winapi keyboard-hook


    【解决方案1】:

    你是如何测试没有调用钩子过程的?如果您尝试使用断点检查它,则必须注意在每个进程中都加载了您的钩子 dll,但您的断点仅放在当前进程中。

    如果您的应用程序中有任何窗口,请在按键或使用日志对其进行调试之前关注它。

    另一种解决方案是与不需要额外 DLL 的 WH_KEYBOARD_LL 挂钩。您可以直接从您的进程中挂钩。

    【讨论】:

      【解决方案2】:

      看看已故的 Paul DiLascia 的代码,它安装了一个全局键盘挂钩来捕获 Ctrl+Alt+Del、任务管理器。 MSDN September 2002 '在 XP 中使用 TrapKeys 禁用键'

      希望这会有所帮助, 最好的祝福, 汤姆。

      【讨论】:

        【解决方案3】:

        这可能与您的主要问题没有直接关系,但是您对 CMyFile 对象的使用有几个问题:

        • CMyFile 对象是使用new CMyFile(...) 动态分配的。这只会在一个进程的内存空间中创建它。

        • pLF 指针未初始化。这意味着它将被放置在 BSS 段而不是共享数据段中。要解决此问题,请使用 CMyFile *pLF = NULL; 声明它。

        • CMyFile 本身可能具有包含文件句柄和/或指针的成员,这些成员在其他进程中无法正常工作。

        关于您的主要问题:

        • 据我所知,您似乎正确地创建了钩子。

        • 在调用 SetWindowsHookEx 时无需强制转换为 HOOKPROC。如果您在没有它的情况下收到警告,则说明您的函数类型有问题。

        • 钩子过程中不需要if 语句 - CallNextHookEx 的第一个参数在现代 Windows 上无论如何都会被忽略,因此两个分支实际上都在做同样的事情。

        • 我不知道我是否信任从不同进程调用的钩子过程上的调试器断点 - 可能调用了该过程但调试器没有捕获它。

        【讨论】:

          【解决方案4】:

          extern "C" 很好,它会摆脱上面提到的名称修饰,但__stdcall 会与此冲突。

          【讨论】:

            【解决方案5】:

            您应该改用RegisterHoyKey API 调用 - 它的麻烦要少得多(我最近在更换类似的键盘挂钩 DLL 时发现自己!)。

            【讨论】:

              【解决方案6】:

              检查您的导出部分是否有 DLL,并查看链接器导出您的“安装”函数的名称。 C++ 使用导出函数名称进行处理。我敢打赌它不是“安装”,而是 _Install@12 或类似的东西。

              【讨论】:

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