6

对于我正在制作的应用程序,我想拦截来自外部进程的窗口消息(很像 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
完毕

如果成功,它应该返回一个标识此事件挂钩实例的 HWINEVENTHOOK 值。如果不成功,它返回 0。(至少根据微软的网站)线程和进程似乎都是有效的并且正在运行。

谁能帮助我更接近我的问题所在?我认为它一定是小东西,或者我只是使用完全错误的方法来做我想做的事情。提前致谢。

4

2 回答 2

7

根据msdn

对于上下文外事件,事件在调用 SetWinEventHook 的同一线程上传递。

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

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

于 2012-12-11T10:58:59.430 回答
6

重点有点不同:

调用 SetWinEventHook 的客户端线程必须有一个消息循环才能接收事件。

( MSDN )

在控制台应用程序中没有消息循环,在 winform 应用程序中有一个。这就是您在控制台应用程序中没有收到事件的原因。

于 2014-10-17T05:53:02.213 回答