gpt4 book ai didi

c++ - 为什么会出现这种行为 - 我的全局 Hook 适用于消息循环但不适用于空循环?

转载 作者:行者123 更新时间:2023-11-28 03:08:31 24 4
gpt4 key购买 nike

首先我会说我是 win32 编程的新手。

我正在使用 .dll 创建一个全局键盘 Hook ,我已经安装和卸载函数来处理键盘 Hook 的实际设置和删除。

#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
static HHOOK hk=NULL;
//static CMyFile *pLF;
#pragma data_seg()

HINSTANCE hins = NULL;

__declspec( dllexport ) LRESULT Install(){
std::cout << "Installing" << std::endl;
hk = SetWindowsHookEx(WH_KEYBOARD_LL,EventAnalysis::KeystrokeAnalysis::KeyboardCallback,hins,0);
if(hk == NULL){
std::cout << "Hook creation failed! - " << GetLastError() << std::endl;
}
return 0;
}


__declspec(dllexport) BOOL CALLBACK UnInstall()
{
std::cout << "UnInstalling" << std::endl;
return UnhookWindowsHookEx(hk);
}

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,我创建了一个简单的可执行文件来加载库并安装 Hook :

int _tmain(int argc, _TCHAR* argv[])
{
auto funHandle = LoadLibrary(L"C:\\Users\\tprodanov\\Documents\\visual studio 2010\\Projects\\HaveFun\\Release\\HaveFun.dll");
if(funHandle == NULL){
std::cout << "Library load failed! - " << GetLastError() << std::endl;
}

auto Install = (LRESULT(*)()) GetProcAddress(funHandle, "?Install@@YAJXZ");
if(Install == NULL){
std::cout << "Procedure load failed! - " << GetLastError() << std::endl;
}
Install();

MSG Msg;

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

auto Uninstall = (BOOL(*)()) GetProcAddress(funHandle, "?UnInstall@@YGHXZ");
if(Uninstall == NULL){
std::cout << "Procedure load failed! - " << GetLastError() << std::endl;
}
Uninstall();
return 0;
}

我觉得奇怪的是,我的程序的行为在其当前状态下符合预期(而且如果不是消息循环,我只是弹出一个等待用户单击“确定”的 MessageBox()),但它如果我使用 std::cin.get() 或空的 while 循环,则不起作用。有人可以解释为什么会这样吗?

还有一个后续问题——KeyboardCallback 函数只是打印到控制台“Key Pressed”。

LRESULT CALLBACK EventAnalysis::KeystrokeAnalysis::KeyboardCallback(int nCode, WPARAM wParam, LPARAM lParam){
std::cout << "Key pressed" << std::endl;
return CallNextHookEx(NULL,nCode,wParam,lParam);
}

我预计这只会在我在控制台窗口上按下按键时打印出来,但即使我在记事本中键入,“按键已按下”消息也会显示在我的可执行文件中,该消息调用了 .dll 的安装函数。我不明白这一点,因为据我所知,动态库在每个进程中都是独立加载的,所以每个进程都有自己的 KeyboardCallback 函数拷贝,它会尝试打印到前台窗口的控制台。

最佳答案

documentation弄清楚发生了什么:

This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.

Hook 是通过调用 Install 安装的。因此,在进行该调用的同一个线程中,您需要运行一个消息循环。

至于为什么显示消息框会影响事物,消息框通过运行模态消息循环来运行。该消息循环将发送 Hook 消息。

对于后续问题,还是 documentation有答案:

The system calls this function every time a new keyboard input event is about to be posted into a thread input queue.

当它说posted into a thread input queue时,它意味着any thread input queue

或者在对SetWindowsHookEx的文档的备注中查看各种 Hook 类型及其范围的列表。 WH_KEYBOARD_LL 被列为全局 Hook 。

另请注意,WH_KEYBOARD_LL 是一个低级 Hook ,因此不会导致 DLL 被注入(inject)到另一个进程中。事实上,您的代码过于复杂。您在这里根本不需要 DLL。您可以通过从您的可执行文件调用 SetWindowsHookEx 来完成这一切,该可执行文件在同一可执行文件中传递回调函数。

这是一个演示所有这些的最小示例程序:

#include <Windows.h>
#include <iostream>

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
std::cout << "Key pressed" << std::endl;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int main(int argc, char* argv[])
{
std::cout << "Installing" << std::endl;
HHOOK hk;
hk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
std::cout << "UnInstalling" << std::endl;
UnhookWindowsHookEx(hk);
return 0;
}

关于c++ - 为什么会出现这种行为 - 我的全局 Hook 适用于消息循环但不适用于空循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19090631/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com