我的目标是在用户与Internet Explorer(iexplore.exe)交互时捕获用户的击键。
这是我的一个名为hook.dll的DLL的DLL代码。
#include <iostream>
#include <windows.h>
extern "C" __declspec(dllexport)
LRESULT keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0) {
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;
}
以下是main.exe的主程序代码:
#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);
}
我用这些命令编译这个项目:
vcvars32.bat
cl /LD hook.cc /link user32.lib
cl main.cc /link user32.lib
当我执行程序时,按下 A , B 和 C 键,我看到以下输出。
C:\>main
hinstDLL: 10000000; fdwReason: 1; lpvReserved: 00000000
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
到目前为止,这一切都很好,但是这个程序可以捕获桌面上任何位置的按键。但我想只捕获在Internet Explorer上进行的那些击键。我相信我需要修改主程序中的SetWindowsHookEx(WH_KEYBOARD, callback, dll, NULL);
调用,并将Internet Explorer的线程ID作为此调用的第四个参数传递。你能帮我解决这个问题吗?
答案 0 :(得分:0)
您有两种解决方案:
1 将SetWindowsHookEx
WH_KEYBOARD
与TID一起使用。这并不容易,因为你必须使用一种机制来检测新线程。
2 对所有主题使用SetWindowsHookEx
WH_GETMESSAGE
。您必须过滤KeyBoard消息和进程名称。这更简单(除了,如果你的EXE是32,你会错过64位进程,或者反过来,除非你构建并运行两个EXE和两个DLL(32/64)。要点:您将能够轻松键入Chrome和Firefox。
答案 1 :(得分:0)
以下是基于manuell建议使用WH_GETMESSAGE
的解决方案代码。
hook.cc中的DLL代码:
#include <iostream>
#include <fstream>
#include <windows.h>
#include <psapi.h>
extern "C" __declspec(dllexport)
LRESULT myHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION) {
std::ofstream outputTxt("C:\\out.txt",
std::ofstream::out | std::ofstream::app);
PMSG msg = (PMSG) lParam;
// Get PID of process
DWORD pid;
GetWindowThreadProcessId(msg->hwnd, &pid);
// Get process name
char filename[1024];
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
GetModuleBaseName(h, NULL, filename, sizeof filename);
// Log details only if it is Internet Explorer
if (msg->message == WM_KEYUP && strcmp(filename, "iexplore.exe") == 0) {
outputTxt << "nCode: " << nCode << "; wParam: " << wParam
<< "; message: " << msg->message
<< "; keycode: " << msg->wParam << " '"
<< char(msg->wParam) << "'"
<< "; filename: " << filename << 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;
}
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, "myHook");
if (callback == NULL) {
std::cerr << "GetProcAddress error " << GetLastError() << std::endl;
return 1;
}
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE, 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);
}
编译此项目如下。
vcvars32.bat
cl /D_WIN32_WINNT=0x0401 /LD hook.cc /link user32.lib /link psapi.lib
cl main.cc /link user32.lib
由于我的EXE是32位,我启动了32位Internet Explorer,点击地址栏并按下键 A , B 和 C 。这是我在C:\ out.txt。
中找到的结果nCode: 0; wParam: 1; message: 257; keycode: 65 'A'; filename: iexplore.exe
nCode: 0; wParam: 1; message: 257; keycode: 66 'B'; filename: iexplore.exe
nCode: 0; wParam: 1; message: 257; keycode: 67 'C'; filename: iexplore.exe
启动64位Internet Explorer,并且做同样的事情在C:\ out.txt中没有产生任何结果。