2012-08-04 91 views
4

对于我正在创建的应用程序,我想拦截来自外部进程的窗口消息(很像spy ++的做法)。我想通了,我可以使用SetWinEventHook来做到这一点。 这是我的代码。C#SetWinEventHook失败(返回0)

 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.(根据微软的网站至少) 线程和进程似乎是有效的和运行。

任何人都可以帮助我更接近我的问题是什么?我认为它一定要么是小事,要么我只是用完全错误的方法去做我想做的事情。提前致谢。

+2

我发现部分问题,应该是使用SetWinEventHookFlags.WINEVENT_OUTOFCONTEXT代替SetWinEventHookFlags.WINEVENT_INCONTEXT。否则它期望我提供一个dll,它可以在其中找到“上下文” – NoCode 2012-08-04 19:38:54

+0

,但仍然没有窗口消息被捕获 – NoCode 2012-08-04 19:39:15

回答

7

根据msdn

对于外的背景事件,该事件被调用SetWinEventHook在同一线程上传递。

我在控制台应用程序中尝试过您的示例,正​​如您所提到的,没有收到任何事件。但在Winform上,该示例运行并收到事件。所以,我认为,这是因为控制台应用程序中的单线程执行。

将SetWinEventHook调用放入按钮单击事件中,您应该开始接收回调中的事件。

3

点是有一点不同:

调用SetWinEventHook必须有消息循环,以便接收事件的客户端线程。

MSDN

里面一个控制台应用程序没有消息循环,在WinForm应用程序有一个。 这就是为什么你不在控制台应用程序中获取事件。

+0

更可能的原因! – tommed 2015-04-20 16:40:15