全局键盘钩不工作

时间:2010-01-24 12:59:27

标签: c++ winapi keyboard-hook

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

Hook是在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的EXe并调用了hook dll的install函数。

 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继续运行,除非我关闭它,但如果我从键盘输入任何其他东西,钩子程序就不会被调用。

这可能是什么原因?

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

6 个答案:

答案 0 :(得分:4)

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

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

另一个解决方案是使用不需要额外DLL的WH_KEYBOARD_LL挂钩。您可以直接从您的流程中挂钩。

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

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

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

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

关于你的主要问题:

  • 就我所见,您似乎正在正确创建钩子。

  • 在调用SetWindowsHookEx时无需强制转换为HOOKPROC。如果在没有它的情况下收到警告,则表示您的功能类型存在问题。

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

你应该使用RegisterHoyKey API调用 - 它不那么麻烦(因为我最近在更换类似的键盘钩子DLL时发现了自己!)。

答案 5 :(得分:0)

检查导出部分是否有DLL,并查看链接器导出“安装”功能的名称。带有导出函数名的C ++ mangles。我打赌你不是“安装”,而是_Install @ 12或类似的东西。