如何为键盘添加钩子 (HookProc)

Alt*_*ter 1 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");
}
Run Code Online (Sandbox Code Playgroud)

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

LPMSG Msg;
while(GetMessage(Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(Msg);
    DispatchMessage(Msg);
}
Run Code Online (Sandbox Code Playgroud)

cab*_*bbi 5

有两种钩子:

全局钩子
全局钩子程序应该放在一个单独的 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); 
Run Code Online (Sandbox Code Playgroud)

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

线程级挂钩
关于在线程级挂钩的特定“WH_KEYBOARD_LL”,它不需要单独的 DLL。

线程特定的挂钩过程仅在关联线程的上下文中调用。如果应用程序为其自己的线程之一安装挂钩过程,则挂钩过程可以与应用程序的其余部分代码位于同一模块中,也可以位于 DLL 中。如果应用程序为不同应用程序的线程安装挂钩过程,则该过程必须在 DLL 中。有关信息,请参阅动态链接库。

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

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

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

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