我的环境详细信息:
我编写了一个名为main.exe的C++程序,该程序进行以下调用:
HOOKPROC callback = (HOOKPROC) GetProcAddress(dll, "keyboardHook");
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, callback, dll, NULL);
keyboardHook
函数在一个名为hook.dll的DLL中定义。此功能记录控制台上的每个按键以及一个名为out.txt的文件。我执行以下实验。
我在控制台上仅看到以下输出。
C:\lab\keyhook>main,exe
hinstDLL: 10000000; fdwReason: 1; lpvReserved: 00000000
); scan code: 28; transition state: 1
nCode: 0; wParam: 65 (A); scan code: 30; transition state: 0
nCode: 0; wParam: 65 (A); scan code: 30; transition state: 1
nCode: 0; wParam: 66 (B); scan code: 48; transition state: 0
nCode: 0; wParam: 66 (B); scan code: 48; transition state: 1
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 0
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 1
nCode: 0; wParam: 17 (◄); scan code: 29; transition state: 0
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 0
hinstDLL: 10000000; fdwReason: 2; lpvReserved: 00000000
hinstDLL: 10000000; fdwReason: 0; lpvReserved: 00000001
我在要登录的文件中仅看到以下输出。
C:\lab\keyhook>type out.txt
); scan code: 28; transition state: 1
nCode: 0; wParam: 65 (A); scan code: 30; transition state: 0
nCode: 0; wParam: 65 (A); scan code: 30; transition state: 1
nCode: 0; wParam: 66 (B); scan code: 48; transition state: 0
nCode: 0; wParam: 66 (B); scan code: 48; transition state: 1
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 0
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 1
nCode: 0; wParam: 17 (◄); scan code: 29; transition state: 0
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 0
您可以看到在控制台或日志文件中均未捕获在32位Chrome上进行的击键。
为什么我的用32位C++编译器编译的32位程序能够成功捕获在64位iexplore.exe上进行的击键,但无法捕获在32位chrome.exe上进行的击键?
MSDN上的SetWindowsHookEx documentation似乎表明我的32位程序应该只能捕获在其他32位程序上进行的击键。
这是调用
SetWindowsHookEx
的主程序的完整代码。// Filename: main.cc
#include <iostream>
#include <windows.h>
int main(int argc, char **argv)
{
HMODULE dll = LoadLibrary("hook.dll");
if (dll == NULL) {
std::cerr << "LoadLibrary error " << GetLastError() << std::endl;
return 1;
}
HOOKPROC callback = (HOOKPROC) GetProcAddress(dll, "keyboardHook");
if (callback == NULL) {
std::cerr << "GetProcAddress error " << GetLastError() << std::endl;
return 1;
}
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, callback, dll, NULL);
if (hook == NULL) {
std::cerr << "SetWindowsHookEx error " << GetLastError() << std::endl;
return 1;
}
MSG messages;
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
UnhookWindowsHookEx(hook);
}
这是DLL代码。
// Filename: hook.cc
#include <iostream>
#include <fstream>
#include <windows.h>
extern "C" __declspec(dllexport)
LRESULT keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
std::ofstream outputTxt("out.txt", std::ofstream::out | std::ofstream::app);
outputTxt << "nCode: " << nCode << "; wParam: " << wParam
<<" (" << char(wParam) << "); scan code: "
<< ((lParam & 0xFF0000) >> 16)
<< "; transition state: " << ((lParam & 0x80000000) >> 31)
<< std::endl;
outputTxt.close();
std::cout << "nCode: " << nCode << "; wParam: " << wParam
<<" (" << char(wParam) << "); scan code: "
<< ((lParam & 0xFF0000) >> 16)
<< "; transition state: " << ((lParam & 0x80000000) >> 31)
<< std::endl;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
std::cout << "hinstDLL: " << hinstDLL
<< "; fdwReason: " << fdwReason
<< "; lpvReserved: " << lpvReserved << std::endl;
return TRUE;
}
这就是我编译该项目的方式:
vcvars32.bat
cl /LD hook.cc /link user32.lib
cl main.cc /link user32.lib
这就是过程的样子。请参见chrome.exe和main.exe是32位进程,而iexplore.exe实例是64位进程。
您能解释为什么我的观察结果与MSDN文档不匹配吗?
最佳答案
汉斯·帕桑(Hans Passant)对这个问题和this answer by manuell的评论帮助我理解和修复了我的代码。
相对路径"out.txt"
是所有困惑的根源。
我的32位程序成功将其32位挂钩插入了32位Chrome。因此,该挂钩在Chrome的上下文中运行,而“out.txt”文件则写在Chrome的工作目录中。因此,在Chrome上作为 Activity 窗口进行的击键X,Y和Z记录在“C:\ Program Files(x86)\ Google \ Chrome \ Application \ 31.0.1650.63 \ out.txt”中。
C:\>type "C:\Program Files (x86)\Google\Chrome\Application\31.0.1650.63\out.txt"
nCode: 0; wParam: 88 (X); scan code: 45; transition state: 0
nCode: 0; wParam: 88 (X); scan code: 45; transition state: 1
nCode: 0; wParam: 89 (Y); scan code: 21; transition state: 0
nCode: 0; wParam: 89 (Y); scan code: 21; transition state: 1
nCode: 0; wParam: 90 (Z); scan code: 44; transition state: 0
nCode: 0; wParam: 90 (Z); scan code: 44; transition state: 1
此输出未出现在控制台中,因为没有控制台与Chrome关联。
但是,我的32位程序无法将其32位挂钩插入到64位Internet Explorer中。结果,该钩子(Hook)在我的程序的上下文中执行,并且当它记录在64位Internet Explorer上进行的击键时,在程序的工作目录中创建了“out.txt”文件。此输出也记录在控制台上,因为有一个与我的程序关联的控制台。这就是您在我的问题中提到的内容。
对我的代码的一个简单修复是将击键记录到绝对路径
"C:\\out.txt"
中,而不是hook.cc中的相对路径“C:\ out.txt”,这样我就可以看到在32位程序和64位程序上进行的击键位程序在同一文件中。关于c++ - 32位程序无法捕获在32位进程上进行的击键,但能够捕获在64位进程上进行的击键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20910872/