3

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

挂钩是在 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 会继续运行,但如果我从键盘输入任何其他内容,则不会调用挂钩过程。

这可能是什么原因?

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

4

6 回答 6

5

How did you test that the hook procedure is not called ? If you tried to check it with a breakpoint, you have to take care that your hook dll is loaded in every process but your breakpoint is only put in your current process.

If you have any window in your application, focus on it before hitting keys or debug it using logs.

Another solution is to hook with WH_KEYBOARD_LL which does not require an extra DLL. You can hook directly from your process.

于 2010-01-25T12:53:47.787 回答
2

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

希望这会有所帮助,最好的问候,汤姆。

于 2010-01-24T14:03:25.917 回答
2

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

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

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

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

关于你的主要问题:

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

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

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

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

于 2010-01-24T17:09:28.110 回答
1

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

于 2011-06-15T15:08:24.063 回答
0

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

于 2011-05-25T19:29:34.867 回答
0

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

于 2010-01-24T17:07:10.277 回答