我创建了一个全局键盘钩子。
Hook是在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的EXe并调用了hook dll的install函数。
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继续运行,除非我关闭它,但如果我从键盘输入任何其他东西,钩子程序就不会被调用。
这可能是什么原因?
这不是设置全局键盘钩子的正确方法吗?
答案 0 :(得分:4)
您是如何测试未调用钩子过程的?如果您尝试使用断点检查它,则必须注意在每个进程中都加载了hook dll,但断点仅放在当前进程中。
如果您的应用程序中有任何窗口,请在按键之前关注它或使用日志对其进行调试。
另一个解决方案是使用不需要额外DLL的WH_KEYBOARD_LL挂钩。您可以直接从您的流程中挂钩。
答案 1 :(得分:2)
看看已故的Paul DiLascia的代码,它安装了一个全局键盘钩子来捕获Ctrl + Alt + Del,任务管理器。 MSDN September 2002' 使用TrapKeys在XP中禁用密钥 '
希望这有帮助, 最好的祝福, 汤姆。
答案 2 :(得分:2)
这可能与您的主要问题没有直接关系,但您使用CMyFile对象有几个问题:
使用new CMyFile(...)
动态分配CMyFile对象。这将仅在一个进程的内存空间中创建它。
pLF
指针未初始化。这意味着它将被放置在BSS段而不是共享数据段中。要解决此问题,请使用CMyFile *pLF = NULL;
声明它。
CMyFile本身可能包含文件句柄和/或指针的成员,这些成员在其他进程中无法正常工作。
关于你的主要问题:
就我所见,您似乎正在正确创建钩子。
在调用SetWindowsHookEx时无需强制转换为HOOKPROC。如果在没有它的情况下收到警告,则表示您的功能类型存在问题。
在钩子proc中不需要if
语句 - 在现代Windows上无论如何都会忽略CallNextHookEx的第一个参数,因此两个分支都有效地做同样的事情。
我不知道我是否相信从不同进程调用的钩子进程上的调试器断点 - 可能会调用该过程,但调试器没有捕获它。
答案 3 :(得分:1)
extern "C"
很好,它将摆脱上面提到的名称修改,但__stdcall
将与此冲突。
答案 4 :(得分:0)
你应该使用RegisterHoyKey API调用 - 它不那么麻烦(因为我最近在更换类似的键盘钩子DLL时发现了自己!)。
答案 5 :(得分:0)
检查导出部分是否有DLL,并查看链接器导出“安装”功能的名称。带有导出函数名的C ++ mangles。我打赌你不是“安装”,而是_Install @ 12或类似的东西。