问题描述
我编写了一个小的 DLL,它被注入到游戏中以应用运行时修复。我决定添加一些键盘监听器:
while (1)
if (AsyncKeyState(...)) (...)
然而,这会占用 cpu 使用率,并引入一些明显的卡顿。所以我决定使用 MSDN 建议的回调方法,通过 SetwindowsHookExA
和 KeyboardProc
回调。起初,我通过 SetwindowsHookExA(WH_Keyboard,KeyboardProc,NULL,0)
运行该方法,但收到错误代码 ERROR_HOOK_NEEDS_HMOD (0x594)
。所以我把我的代码改成了这样:
bool APIENTRY DllMain(HMODULE hModule,DWORD reason,LPVOID lpRes)
{
HHOOK hook_ = nullptr;
switch (reason)
{
case DLL_PROCESS_ATTACH:
if (!(hook_ = SetwindowsHookEx(WH_KEYBOARD,hModule,0)))
{
char x[100];
sprintf(x,"Failed To Hook Keyboard FN: 0x%X",GetLastError());
MessageBox(NULL,x,"Error",MB_ICONERROR);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
UnhookWindowsHookEx(hook_);
break;
}
return true;
}
这不再出现错误,而且我的挂钩键盘功能运行良好。然而,一个非常意想不到的副作用是所有正在运行的应用程序的所有键盘捕获都被忽略了。 我注意到 MSDN 上的这句话,所以我将它添加到我的代码中:
如果code大于等于0,且钩子过程没有处理消息,强烈建议调用CallNextHookEx并返回它返回的值;否则,安装了 WH_KEYBOARD 钩子的其他应用程序将不会收到钩子通知,因此可能会出现不正确的行为。如果钩子过程处理了消息,它可能会返回一个非零值以防止系统将消息传递给钩子链的其余部分或目标窗口过程。
这解决了键盘问题,但现在还有另一个问题,即我无法删除我创建的 DLL。当我尝试删除它时,它说“dll 正在 Explorer.exe 中运行”。当我杀死 explorer.exe
时,它说“dll 正在 SteamHelper.exe 中运行”。当我杀死 steamhelper.exe
时,它说“dll 正在 Chrome.exe 中运行”。这表明我以某种方式迷上了每个正在运行的应用程序?
我无法解决这个问题,也找不到任何帮助。非常感谢任何见解!
解决方法
您正在挂钩每个应用程序进程,因为您正在全局安装挂钩,方法是将 dwThreadId
的 SetWindowsHookEx()
参数设置为 0:
dwThreadId
类型:DWORD
与钩子过程关联的线程的标识符。对于桌面应用程序,如果此参数为零,则挂钩过程与在调用线程所在的同一桌面上运行的所有现有线程相关联。对于 Windows 应用商店应用,请参阅备注部分。
相反,您应该将该参数设置为要为其挂钩事件的游戏线程的实际线程 ID。