使用SetWindowsHookEx监控窗口创建与销毁的问题求助
Hey there, let's break down why your WH_GETMESSAGE hook isn't behaving as expected and walk through the fixes you need to apply. The key differences between your working WH_KEYBOARD_LL hook and this WH_GETMESSAGE attempt are critical here—let's unpack them:
Core Issues in Your Current Code
1. WH_GETMESSAGE Hook Scope & Architecture
Unlike WH_KEYBOARD_LL (a low-level hook that works globally without DLL injection), WH_GETMESSAGE operates differently:
- If you pass
0as the last parameter toSetWindowsHookEx, it only hooks messages in your current thread—so you won't see messages from other windows/applications. - To monitor messages across all processes (like WM_CREATE/WM_DESTROY from any window), you need a global WH_GETMESSAGE hook, which requires your hook procedure to live inside a DLL. This is because other processes need to load the DLL to execute your hook code in their address space.
2. Incorrect GetModuleFileNameEx Usage
Your code calls GetModuleFileNameEx(m.hwnd, 0, Buffer, MAX_PATH)—but the first parameter of this function is a process handle, not a window handle. You need to:
- Get the process ID associated with the window using
GetWindowThreadProcessId - Open the process with
OpenProcessto get a valid handle - Then call
GetModuleFileNameExwith that process handle
3. Broken Hook Chain & Unfiltered Messages
- When
wParam != PM_REMOVE, you returnNULLinstead of callingCallNextHookEx. This breaks the hook chain, preventing other hooks from receiving messages and can cause unexpected system behavior. - You're not filtering for
WM_CREATEorWM_DESTROY—your code tries to process every message, which is inefficient and not what you intended.
Fixed Implementation
To make this work, you'll need two parts: a DLL containing the hook procedure, and a test application to set/release the hook.
Part 1: Hook DLL Code
#include <windows.h> #include <tchar.h> #include <psapi.h> #pragma comment(lib, "psapi.lib") HHOOK g_hHook = NULL; // Hook procedure LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0 && wParam == PM_REMOVE) { MSG* pMsg = reinterpret_cast<MSG*>(lParam); // Filter for the messages we care about if (pMsg->message == WM_CREATE || pMsg->message == WM_DESTROY) { DWORD dwProcessId = 0; GetWindowThreadProcessId(pMsg->hwnd, &dwProcessId); // Open the process to get its module path HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId); if (hProcess != NULL) { TCHAR szExePath[MAX_PATH] = {0}; if (GetModuleFileNameEx(hProcess, NULL, szExePath, MAX_PATH)) { TCHAR szMsg[512]; _stprintf_s(szMsg, _T("Window %s: %s"), (pMsg->message == WM_CREATE) ? _T("Created") : _T("Destroyed"), szExePath); MessageBox(NULL, szMsg, _T("Window Event"), MB_ICONINFORMATION); } CloseHandle(hProcess); } } } // Always pass the message to the next hook in the chain return CallNextHookEx(g_hHook, nCode, wParam, lParam); } // Exported function to set the hook extern "C" __declspec(dllexport) BOOL SetGlobalGetMsgHook() { g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, GetModuleHandle(_T("MsgHook.dll")), 0); return (g_hHook != NULL); } // Exported function to release the hook extern "C" __declspec(dllexport) void ReleaseGlobalGetMsgHook() { if (g_hHook != NULL) { UnhookWindowsHookEx(g_hHook); g_hHook = NULL; } } // DLL entry point BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
Part 2: Test Application Code
#include <windows.h> #include <tchar.h> // Function prototypes for DLL exports typedef BOOL(*SetHookFunc)(); typedef void(*ReleaseHookFunc)(); int _tmain() { // Load the hook DLL HMODULE hDll = LoadLibrary(_T("MsgHook.dll")); if (hDll == NULL) { MessageBox(NULL, _T("Failed to load hook DLL!"), _T("Error"), MB_ICONERROR); return 1; } // Get pointers to the exported functions SetHookFunc SetHook = reinterpret_cast<SetHookFunc>(GetProcAddress(hDll, "SetGlobalGetMsgHook")); ReleaseHookFunc ReleaseHook = reinterpret_cast<ReleaseHookFunc>(GetProcAddress(hDll, "ReleaseGlobalGetMsgHook")); if (!SetHook || !ReleaseHook) { MessageBox(NULL, _T("Failed to get DLL functions!"), _T("Error"), MB_ICONERROR); FreeLibrary(hDll); return 1; } // Set the global hook if (!SetHook()) { MessageBox(NULL, _T("Failed to install hook!"), _T("Error"), MB_ICONERROR); FreeLibrary(hDll); return 1; } MessageBox(NULL, _T("Hook installed successfully. Click OK to exit and release hook."), _T("Info"), MB_ICONINFORMATION); // Release the hook and unload DLL ReleaseHook(); FreeLibrary(hDll); return 0; }
Key Notes for Success
- Compile the DLL as a 32-bit or 64-bit binary to match the target processes (e.g., 32-bit DLL for 32-bit apps, 64-bit for 64-bit apps—you can't mix architectures).
- Run the test application with administrative privileges—some processes may require elevated rights to hook.
- Be cautious with global hooks—they can impact system performance if not optimized, and misbehaving hooks can cause instability.
内容的提问来源于stack exchange,提问作者Amumu

