2012-08-04 151 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