对于我正在制作的应用程序,我想拦截来自外部进程的窗口消息(就像spy ++那样)。我发现我可以使用SetWinEventHook来做到这一点。 这是我的代码。
class Program
{
internal delegate void WinEventProc(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime);
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, int idProcess, int idThread, SetWinEventHookFlags dwflags);
//[DllImport("user32.dll", SetLastError = true)]
internal static extern int UnhookWinEvent(IntPtr hWinEventHook);
internal enum SetWinEventHookFlags
{
WINEVENT_INCONTEXT = 4,
WINEVENT_OUTOFCONTEXT = 0,
WINEVENT_SKIPOWNPROCESS = 2,
WINEVENT_SKIPOWNTHREAD = 1
}
static void Main(string[] args)
{
int threadId = 0x000306D4;
int processId = 0x000306BC;
WinEventProc listener = new WinEventProc(EventCallback);
//setting the window hook and writing the result to the console
Console.WriteLine(SetWinEventHook(1, 0x7fffffff, IntPtr.Zero, listener, processId, threadId, SetWinEventHookFlags.WINEVENT_INCONTEXT).ToString());
Console.WriteLine("done");
Console.ReadKey();
}
private static void EventCallback(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime)
{
//callback function, called when message is intercepted
Console.WriteLine(hWnd.ToString());
}
}
}
据我所知,我正在使用正确的P / Invoke声明,但是当我运行此代码时输出为:
0 done
如果成功,它应返回标识此事件挂钩实例的HWINEVENTHOOK值。如果不成功则返回0.(至少根据微软的网站) 线程和进程似乎都是有效的并且正在运行。
有人能帮助我更接近我的问题所在吗?我认为它必须是小的东西,或者我只是使用完全错误的方法来做我想做的事情。提前谢谢。
答案 0 :(得分:7)
根据msdn
对于上下文事件,事件在调用SetWinEventHook的同一线程上传递。
我在控制台应用中尝试了您的示例,正如您所提到的,没有收到任何事件。但是在winform上,该示例有效并且接收到事件。所以,我认为,这是因为控制台应用程序中的单个执行线程。
将SetWinEventHook调用置于按钮单击事件中,您应该开始在回调中接收事件。
答案 1 :(得分:3)
关键点有点不同:
调用SetWinEventHook的客户端线程必须有一个消息循环才能接收事件。
(MSDN)
在控制台应用程序内部没有消息循环,在winform应用程序中有一个消息循环。 这就是您在控制台应用中获取活动的原因。