我有一个被进程调用的dll,现在我想在dll中实现一个输入检查,以对应用程序中发生的某些输入作出反应。
具有SetWindowsHookEx()
功能的 KeyboardProc
似乎是一种可能的解决方案,因此我实施了它。
这大致是dll中代码的样子:
static HHOOK hhk = NULL;
LRESULT CALLBACK keyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code == HC_ACTION && ((DWORD)lParam & 0x80000000) == 0) // if there is an incoming action and a key was pressed
{
switch(wParam)
{
case VK_SPACE:
printf("Space was pressed\n");
break;
}
}
return CallNextHookEx(hhk, code, wParam, lParam);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if(AllocConsole()){
freopen("CONOUT$", "w", stdout); // redirect output to console for debugging
}
printf("Dll loaded, lastError = %i\n", GetLastError());
printf("lastError = %i\n", GetLastError());
// sidenote: for some reason the first GetLastError() returns 0 while the second one returns 6 (invalid handle)
hhk = SetWindowsHookEx(WH_KEYBOARD, keyboardProc, hModule, GetCurrentThreadId());
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
printf("\nCleaning up...");
FreeConsole();
UnhookWindowsHookEx(hhk);
}
return TRUE;
}
然而,当我按任意键时,控制台窗口中没有任何反应(或被打印)。它似乎甚至不会随时访问keyboardProc
函数。
当我将NULL
而不是GetCurrentThreadId()
传递给SetWindowsHookEx()
时 工作。
但这会导致钩子全局工作,这意味着每当我按下另一个应用程序中的某个键时,就会弹出一个控制台窗口(因为dll再次被调用)并且他在那里检查键输入。
显然这不是我们想要的,我想只使用最初调用dll的进程来完成这项工作。
我已经检查过GetCurrentThreadId()
是否返回了有效的ID,它似乎确实是最初调用dll的进程的主线程ID(使用Process Explorer检查)。
所以现在我的问题是什么可能是问题,更重要的是,我该怎么做才能让它发挥作用?
答案 0 :(得分:-1)
public int compareTo(Client c)
我已经使用上面的代码来获取某个进程的主要thread_ID。好的部分是,SetWindowsHookEx函数提供逻辑输出。不幸的是,坏的部分是,如果在已挂钩的线程中按下某个键,则该线程将停止工作。
具体来说,在我的情况下,对于非低级键盘事件,SetWindowsHoookEx函数的idHook参数设置为2(而不是13)。至少在我看来,LL对应于低级别,其中keyboardProc应该带有WH_KEYBOARD而不是WH_KEYBOARD_LL。
此时我不确定我的回答会如何与您的问题相关。希望我们通过讨论得到我们需要的东西。