簡體   English   中英

SetWindowsHookEx 不適用於另一個進程線程 ID 上的 WH_CBT(但適用於自己的線程 ID)

[英]SetWindowsHookEx not working with WH_CBT on another process thread ID (but works on own thread ID)

幾天來我一直在絞盡腦汁,可以使用一些幫助! 當 CBT 掛鈎連接到我的 WPF 應用程序的線程 ID 時,我能夠使用 SetWindowsHookEx 檢測到它,但是當該窗口成為前台應用程序時,我無法讓它掛鈎到另一個進程窗口的線程 ID .

圖 1:顯示我可以在主應用程序的線程 ID 上獲取用於檢測窗口最大化的 CBT 鈎子圖 1:顯示我可以在主應用程序的線程 ID 上獲取用於檢測窗口最大化的 CBT 鈎子

圖 2:顯示我在偵聽另一個應用程序的線程 ID 時無法獲取 CBT 鈎子,並且會使應用程序崩潰! 圖 2:顯示我在偵聽另一個應用程序的線程 ID 時無法獲取 CBT 鈎子,並且會使應用程序崩潰!

我想避免發送 ThreadId=0 並使其成為一個完整的全局鈎子,因為我知道我只想聽前台應用程序,而不是桌面上的所有應用程序。 對於當前具有前景焦點的任何窗口,我希望能夠在它們發生之前監聽一些窗口事件(WH_CBT 根據我的理解這樣做)。

同樣,當當前 WPF 應用程序成為前台應用程序時,以下代碼有效,但當另一個應用程序的窗口成為前台(例如記事本、Internet Explorer、文件資源管理器、Chrome 等)時,它會失敗。

完整代碼:( 鏈接到 github zip 文件)

以下是一些代碼片段,以顯示我所做的事情:

定義回調的 DLL (inject.dll):

注入.h:代碼段
typedef void(__stdcall* MYFUNCPTR)(int code, WPARAM wparam, LPARAM lparam); extern "C" __declspec(dllexport) void Init(MYFUNCPTR funcPtr); extern "C" __declspec(dllexport) LRESULT CALLBACK CbtProcCallback(int code, WPARAM wparam, LPARAM lparam); WPARAM wparam, LPARAM lparam); MYFUNCPTR _handler = 0;
注入.cpp:片段
public delegate void MessageCallback(string message);
public delegate void CodeCallback(int code, IntPtr wParam, IntPtr lParam);
[DllImport("dllwrapper.dll")]
public extern static bool StartHooks(uint threadId, MessageCallback messageHandler, CodeCallback codeHandler);
[DllImport("dllwrapper.dll")]
public extern static void StopHooks();

設置 CBT 掛鈎的 DLL (dllwrapper.dll):

dllwrapper.cpp:代碼段
 // Load library in which we'll be hooking our functions. HMODULE dll = LoadLibrary(L"inject.dll"); if (dll == NULL) { char errorMessage[100]; sprintf_s(errorMessage, "ERR-LoadLibrary failed! ErrorCode=%d", GetLastError()); SendManagedMessage(errorMessage); return false; } SendManagedMessage("LoadLibrary passed!"); // Get the address of the function inside the DLL. MYPROC iaddr = (MYPROC)GetProcAddress(dll, "Init"); if (iaddr == NULL) { char errorMessage[100]; sprintf_s(errorMessage, "ERR-GetProcAddress for Init failed! ErrorCode=%d", GetLastError()); SendManagedMessage(errorMessage); return false; } SendManagedMessage("GetProcAddress for Init passed!"); iaddr(OnInjectionCallback); // Get the address of the function inside the DLL. HOOKPROC cbtProcAddress = (HOOKPROC)GetProcAddress(dll, "CbtProcCallback"); if (cbtProcAddress == NULL) { char errorMessage[100]; sprintf_s(errorMessage, "ERR-GetProcAddress for CbtProcCallback failed! ErrorCode=%d", GetLastError()); SendManagedMessage(errorMessage); return false; } SendManagedMessage("GetProcAddress for CbtProcCallback passed!"); // Hook the function cbtProcHook = SetWindowsHookEx(WH_CBT, cbtProcAddress, dll, _threadId); if (cbtProcHook == NULL) { char errorMessage[100]; sprintf_s(errorMessage, "ERR-SetWindowsHookEx cbtProcAddress failed! ErrorCode=%d", GetLastError()); SendManagedMessage(errorMessage); return false; } SendManagedMessage("SetWindowsHookEx for cbtProcAddress passed!");
片段導出到 C#
 typedef void(__stdcall* CodeCallback)(int code, WPARAM wparam, LPARAM lparam); typedef void(__stdcall* MessageCallback)(const char* message); #ifdef __cplusplus extern "C" { // only need to export C interface if // used by C++ source code #endif __declspec(dllexport) bool StartHooks(unsigned int threadId, MessageCallback messageCallback, CodeCallback codeCallback); __declspec(dllexport) void StopHooks(); #ifdef __cplusplus } #endif
NativeMethods.cs:C# dll 導入到 WPF 應用程序的片段
public delegate void MessageCallback(string message); public delegate void CodeCallback(int code, IntPtr wParam, IntPtr lParam); [DllImport("dllwrapper.dll")] public extern static bool StartHooks(uint threadId, MessageCallback messageHandler, CodeCallback codeHandler); [DllImport("dllwrapper.dll")] public extern static void StopHooks();

我可以從 WPF 應用程序窗口中的消息中看到鈎子正在傳遞並且不返回任何 Win32 錯誤,但是當另一個窗口具有焦點時(即使使用調試器時),它也不會執行回調。

任何幫助將不勝感激!

開發環境:

  • 視窗 10 1909
  • VS2019 16.7.4
  • C# .NET 框架 4.7.2,C++

當主應用程序調用Init() ,它正在調用自己的 DLL 實例,並設置自己的_handler副本。

當您的鈎子 DLL 被注入另一個進程時,該進程將獲得自己的 DLL 副本,從而獲得自己的_handler副本。 但是Init()永遠不會在那個 DLL 實例上被調用,所以當你的鈎子函數在那個進程中被調用時,它的_handler副本仍然是 0。 這就是進程崩潰的原因,因為鈎子沒有檢查該條件。

另一個進程中的 DLL 無法跨進程邊界調用主應用程序中的函數。 _handler為 0 時,您將不得不更改鈎子函數以使用您選擇的 IPC 機制與主應用程序進程通信。窗口消息、管道、郵槽、套接字等可用於該通信。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM