SendMessage(hwnd, registeredmssghere, 0, 1) 已接收但未被其发送到的挂钩线程正确识别!

Posted

技术标签:

【中文标题】SendMessage(hwnd, registeredmssghere, 0, 1) 已接收但未被其发送到的挂钩线程正确识别!【英文标题】:SendMessage(hwnd, registeredmssghere, 0, 1) received but not correctly recognized by hooked thread its sent to! 【发布时间】:2011-06-30 15:03:18 【问题描述】:

我正在尝试将用户注册的消息发送到窗口程序,程序收到一条消息但它看不到我正在发送的特定注册消息。

所以从一开始...我确保所有 dll 实例共享消息。

#pragma data_seg (".shared") ... ... UINT WM_HOOKEX = 0; ... #pragma data_seg () #pragma 注释(链接器,“/SECTION:.shared,RWS”)

在 dllmain 中我确保它只注册一次

BOOL APIENTRY DllMain( 处理 hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) 如果(ul_reason_for_call == DLL_PROCESS_ATTACH) hDll = (HINSTANCE) hModule; //DisableThreadLibraryCalls(hDll); 如果(WM_HOOKEX==NULL) WM_HOOKEX = ::RegisterWindowMessage(_T("WM_HOOKEX_RK")); 返回真;

稍后使用我在我的应用程序中使用的导出 dll 函数(共享 dll 和消息),我连接到所需窗口的过程并使用

发送此消息 SendMessage(plist,WM_HOOKEX,0,1);

钩子程序接收到消息(因为我正在使用 dll 调试检查它)但它看不到它是什么消息。 Dll 调试显示线程已在其内存中注册了消息,但过程没有收到正确的消息参数。

我还确定它正在接收此消息而不是其他消息,因为这是指向我调用的过程的唯一消息,所以我排除了我的自定义 mssg 可能仍在队列中的可能性,那么为什么我想知道为什么这几天,为什么它没有收到消息,因为它甚至应该调试表明它在它的内存中保存了自定义消息!

这是接收它的过程(或实际上没有)

#define pCW ((CWPSTRUCT*)lParam) LRESULT HookProc ( int code, // 钩子代码 WPARAM wParam, // 虚拟键码 LPARAM lParam // 击键消息信息 ) if( (pCW->message == WM_HOOKEX) && pCW->lParam ) ::UnhookWindowsHookEx(g_hHook); 如果(g_bSubclassed) 转到结束; // 已经子类化了? // 让我们增加 DLL 的引用计数(通过 LoadLibrary), // 所以一旦钩子被移除,它就不会被取消映射; TCHAR lib_name[MAX_PATH]; ::GetModuleFileName(hDll, lib_name, MAX_PATH); if(!::LoadLibrary(lib_name)) 转到结束; // 子类开始按钮 OldProc = (WNDPROC) ::SetWindowLong(g_hWnd, GWL_WNDPROC, (long)NewProc); if( OldProc==NULL ) // 失败? ::FreeLibrary(hDll); else // 成功 -> 离开 "HookInjEx.dll" ::MessageBeep(MB_OK); // 映射到“explorer.exe” g_bSubclassed = true; 否则如果(pCW->message == WM_HOOKEX) ::UnhookWindowsHookEx(g_hHook); // 恢复旧窗口程序失败? => 不要取消映射 // DLL。为什么?因为那时“explorer.exe”会调用我们的 // “未映射” NewProc 并崩溃!! if( !SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc ) ) 转到结束; ::FreeLibrary(hDll); ::MessageBeep(MB_OK); g_bSubclassed = false; 结尾: 返回 ::CallNextHookEx(g_hHook, 代码, wParam, lParam);

我怀疑所有这一切都与我发送带有导出函数的消息有关,该导出函数是从我的应用程序调用的。如果我使用原始项目附带的示例应用程序中的函数执行此操作,它使用导入的函数,我认为可能是导出的函数。

我也无法将导入的函数作为其他语言进行测试。

编辑:

所以我也尝试每次都按照这里的建议注册 mssg,但这并没有什么不同,这里奇怪的是,如果我调用内部挂钩和发送 mssg 的函数,一切正常,这是函数的标题gui 应用程序使用的(在这种情况下一切正常)

#if !defined INJECT_EX__H #define INJECT_EX__H #ifdef INJECT_EX_EXPORTS #define HOOKDLL_API __declspec(dllexport) #别的 #define HOOKDLL_API __declspec(dllimport) #万一 extern int HOOKDLL_API g_bSubclassed; HOOKDLL_API int InjectDll(); HOOKDLL_API int UnmapDll(); #endif // !defined(INJECT_EX__H) #define DIPSLIBAPI extern "C" __declspec(dllexport) // 外部函数原型 DIPSLIBAPI BOOL WINAPI SetDIPSHook(BOOL hook_it, BOOL just_save_list, int lobby, int type);

所以这是我相信gui应用程序使用injectdll函数作为导入函数的标题,也许这就是它起作用的原因?如果我使用没有此标头的导出函数,则 mssg 不正确。

编辑2:

以下是来自 dll 项目的预处理器指令: _调试 WIN32 _视窗 _USRDLL INJECT_EX_EXPORTS

【问题讨论】:

Why is wparam changing if i use same message, with same paras?的可能重复 【参考方案1】:

我不完全清楚你描述的问题是什么。我猜这将对应于如果 WM_HOOKEX 在注入的 dll 中仍然为 0 时你会得到的行为。假设这是问题所在,您需要执行以下操作:

volatile UINT WM_HOOKEX = 0;

这确保编译器不会优化对 WM_HOOKEX 的引用,而是在每次使用它时从内存中读取它。

【讨论】:

我放弃了,我正在使用静态布尔值来检测是否发送了第一条消息,谢谢【参考方案2】:

一个特别的问题是你应该调用 ::RegisterWindowMessage( _T("WM_HOOKEX_RK") );在您希望接收它的每个过程中。系统将在任何进程中向您返回相同的消息编号,该消息已在系统范围内注册。

【讨论】:

我认为您不必在每个过程中都调用RegisterWindowMessage,以防您通过其他方式知道消息ID。消息注册后 - 将获得其唯一 ID,从现在开始,它与其他消息无法区分。

以上是关于SendMessage(hwnd, registeredmssghere, 0, 1) 已接收但未被其发送到的挂钩线程正确识别!的主要内容,如果未能解决你的问题,请参考以下文章

如何用 sendmessage 发送键盘按键消息

SendMessage, postmessage模拟鼠标左键

delphi中使用 SendMessage(HWND_BROADCAST,WM_WININICHANGE,0,0);软件卡死,怎么解决?

c中如何用SendMessage()向Notepad发送消息? 在执行文件中输入,在指定记事本中显示

获取其它进程窗口中的状态栏信息(FindWindowEx GetWindowThreadProcessId OpenProcess SendMessage轮番轰炸)

python 通过句柄获取窗口内容