如何为Keyboard(HookProc)添加一个钩子

时间:2014-11-21 20:51:21

标签: c++ windows hook

我试图做一个简单的键盘测试,但我的程序没有按预期工作,我不知道为什么。

在我的程序中,我有一个低级键盘钩子并附加一个简单的过程。该过程只是打开/创建一个文件并写入“Hello World”然后关闭。但是它不是创建文件,可能是因为我的进程不正确或因为我的钩子没有正确建立。

代码:

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

using namespace std;

LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam){
    ofstream myfile;
        myfile.open ("[PATH]/example.txt");
        myfile << "Hello world";//((KBDLLHOOKSTRUCT *)lParam)->vkCode
    myfile.close();
    return CallNextHookEx(NULL,code,wParam,lParam);
}

int main(void){
    HINSTANCE hInst = NULL;
    HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hInst, 0);
    printf("HHOOK is not null: %s\n", (hHook != NULL) ? "True" : "False");
    char q;
    for (cout << "q to quit\n"; q != 'q'; cin >> q);

    printf("Successfully unhooked: %s", UnhookWindowsHookEx(hHook) ? "True" : "False");
}

解决方案我需要在主函数中添加一个消息循环:

LPMSG Msg;
while(GetMessage(Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(Msg);
    DispatchMessage(Msg);
}

1 个答案:

答案 0 :(得分:4)

这是两种钩子:

Global Hooks
全局钩子程序应该放在一个单独的DLL中,然后在你的主进程中加载​​钩子dll和它的钩子程序并设置钩子。

  

全局钩子监视同一桌面中所有线程的消息   调用线程。特定于线程的挂钩仅监视消息   个人主题。可以在中调用全局钩子过程   与调用线程在同一桌面中的任何应用程序的上下文,   所以程序必须在一个单独的DLL模块中。

那说:KeyboardProc进入一个单独的DLL(例如myhookdll.dll) 在您的过程中,您可以执行以下操作:

HOOKPROC hkprc;
static HINSTANCE hhookDLL ; 
static HHOOK hhook ; 

hhookDLL = LoadLibrary(TEXT("c:\\...\\myhookdll.dll")); 
hkprc = (HOOKPROC)GetProcAddress(hhookDLL, "KeyboardProc"); 

hhook = SetWindowsHookEx( 
                    WH_KEYBOARD,
                    hkprc,
                    hhookDLL,
                    0); 

这是一个很好的参考:http://msdn.microsoft.com/en-us/library/windows/desktop/ms644960(v=vs.85).aspx

主题级别挂钩
关于此特定&#39; WH_KEYBOARD_LL&#39;挂钩在线程级别,它不需要单独的DLL。

  

特定于线程   钩子过程仅在关联线程的上下文中调用。   如果应用程序为其自己的某个安装了一个钩子过程   线程,钩子程序可以在与...相同的模块中   其余的应用程序代码或DLL。如果申请   为不同应用程序的线程安装一个钩子程序   过程必须在DLL中。有关信息,请参阅动态链接   库。

但是线程级钩子需要一个消息泵:

  

在安装它的线程的上下文中调用此钩子。   通过向安装了该安装的线程发送消息来进行调用   钩。因此,安装钩子的线程必须有一个   消息循环。

这是一个基本的消息循环:

   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
   {
     if(bRet == -1)
     {
         // Handle Error
     }
     else
     {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
     }
   }