前提・実現したいこと
SetWindowsHookEx関数で、特定スレッドのメッセージをフックしたいです。
フックの種類は「WH_CALLWNDPROC」で、C++でフックプロシージャのDLLを作成し、C#から呼び出しています。
DLL、メインのアプリケーション、フック対象のソフト、すべて32bitです(OSは64bit)。
発生している問題
SetWindowsHookEx関数の引数4(dwThreadId)にスレッドIDを指定すると、一切メッセージがフックされません。
0 を指定してグローバルフックにすると、フックされるのですが……
該当のソースコード
メモ帳を起動し、その起動したメモ帳に対してフックします。
DLL側(dllmain.cpp)
※「HookProc.dll」という名前で生成しています
C++
1// dllmain.cpp : DLL アプリケーションのエントリ ポイントを定義します。 2#include "pch.h" 3#include <iostream> 4 5// エクスポート 6#define DllExport __declspec(dllexport) BOOL __stdcall 7extern "C" { 8 DllExport SetHook(DWORD threadId); 9 DllExport UnHook(void); 10} 11 12#pragma data_seg(".shared") // 何のため? 13HHOOK hHook = NULL; 14#pragma data_seg() 15 16HINSTANCE hInstance; 17 18 19BOOL APIENTRY DllMain( HMODULE hModule, 20 DWORD ul_reason_for_call, 21 LPVOID lpReserved 22 ) 23{ 24 switch (ul_reason_for_call) 25 { 26 case DLL_PROCESS_ATTACH: 27 hInstance = hModule; 28 break; 29 } 30 return TRUE; 31} 32 33LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) 34{ 35 if (nCode == HC_ACTION) 36 { 37 char buffer[256] = ""; 38 const LPCWPSTRUCT lpcwprs = (LPCWPSTRUCT)lParam; 39 sprintf_s(buffer, 255, "HC_ACTION message: %X, lParam: %d, wParam: %d, hwnd: %d", int(lpcwprs->message), int(lpcwprs->lParam), int(lpcwprs->wParam), int(lpcwprs->hwnd)); 40 std::cout << buffer << std::endl; 41 } 42 return CallNextHookEx(hHook, nCode, wParam, lParam); 43} 44 45BOOL APIENTRY SetHook(DWORD threadId) 46{ 47 hHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, hInstance, threadId); 48 49 if (hHook == NULL) 50 { 51 return false; 52 } 53 else 54 { 55 return true; 56 } 57} 58 59BOOL APIENTRY UnHook(void) 60{ 61 bool ret = UnhookWindowsHookEx(hHook); 62 hHook = NULL; 63 return ret; 64} 65
呼び出す側(Form1.cs)
C#
1using System; 2using System.Runtime.InteropServices; 3using System.Windows.Forms; 4 5namespace MessageHook 6{ 7 public partial class Form1 : Form 8 { 9 public Form1() 10 { 11 InitializeComponent(); 12 } 13 14 15 [DllImport("HookProc.dll")] 16 extern static bool SetHook(uint threadId); 17 [DllImport("HookProc.dll")] 18 extern static bool UnHook(); 19 20 [DllImport("user32.dll", SetLastError = true)] 21 static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 22 [DllImport("user32.dll")] 23 static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 24 25 private void Form1_Load(object sender, EventArgs e) 26 { 27 // メモ帳(32bit)を対象にフックする 28 System.Diagnostics.Process p = System.Diagnostics.Process.Start("notepad.exe"); 29 System.Threading.Thread.Sleep(100); 30 IntPtr notepadWndHandle = FindWindow("Notepad", null); 31 uint threadId = GetWindowThreadProcessId(notepadWndHandle, IntPtr.Zero); 32 if (threadId == 0) 33 { 34 Console.WriteLine("スレッドIDの取得に失敗"); 35 Close(); 36 } 37 else 38 { 39 bool ret = SetHook(threadId); 40 Console.WriteLine("SetHook: " + ret); 41 } 42 } 43 44 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 45 { 46 bool ret = UnHook(); 47 Console.WriteLine("UnHook: " + ret); 48 } 49 } 50} 51
試したこと
- Microsoftのドキュメントを読みましたが、関係することは書かれていませんでした。
SetWindowsHookExA function (winuser.h) - Win32 apps | Microsoft Docs
どこを直せば実現できるのでしょうか?
回答よろしくお願いします。
補足情報(FW/ツールのバージョンなど)
- Visual Studio 2019
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/06/13 05:15 編集
2021/06/14 09:33
2021/06/14 13:11
2021/06/15 08:19