2012-12-11 29 views
0

當一個不同的C#應用​​程序(表單)即將關閉時,我想在我的C#應用​​程序中收到一個事件。C#訂閱FormClosing

我該如何做到這一點?這可以用Reflections完成嗎?

編輯:詳細說明

我意識到我原來的問題是不是很具體。 我會嘗試更詳細地描述我的目標。

所以我有3個應用程序。讓我們將它們命名爲容器,PlacerToPlace。 我發展Contaner砂礦在C#中,普萊瑟是一個DLL,而集裝箱是一個WinForm。我無法訪問ToPlace的源代碼。在容器我有一個自定義控件,我把它放在主窗口ToPlace與SetParent從Placer調用。目標是在關閉應用程序之前恢復父窗口,或者過濾掉髮送到主窗口的WM_DESTROY消息(或其他消息)。最終的目標不是破壞ToPlace的主窗口,當Container退出。

我試圖覆蓋Container中的自定義控件的WndProc,但不會通過父窗口發送到子窗口的消息。

我也嘗試在Container應用程序上安裝消息過濾器,但這也不是成功的。

我在寫這個問題之前的最後一次嘗試是SetWindowsHookEx,但是在成功安裝了鉤子之後,鉤子程序從不會被調用。也許是因爲我在某處讀過,鉤子函數必須位於win32 dll中,而不是託管函數中。接下來的嘗試將是使用SetWinEventHook,我讀過關於它更容易從C#中獲得它的工作。

我和SetWindowsHookEx嘗試的代碼如下,也許有人是誰在C#互操作更有經驗,看到一個錯誤,可以得到它的工作:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace AppMonitor 
{ 
    public class AppMonitor 
    { 
     private const int WH_GETMESSAGE = 3; 
     private const int HC_ACTION = 0; 
     private const int PM_NOREMOVE = 0x0000; 
     private const int PM_REMOVE = 0x0001; 
     private const int WM_QUIT = 0x0012; 

     [DllImport("user32.dll")] 
     private static extern int SetWindowsHookEx(int idHook, GetMsgProcDelegate lpfn, int hMod, int dwThreadId); 

     [DllImport("user32.dll")] 
     private static extern bool UnhookWindowsHookEx(int hhk); 

     [DllImport("user32.dll")] 
     private unsafe static extern int CallNextHookEx(int hhk, int nCode, int wParam, void* lParam); 

     [DllImport("user32.dll")] 
     private static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); 

     [DllImport("kernel32.dll")] 
     private static extern int GetLastError(); 

     private struct Msg { 
      public int  hwnd; 
      public int  message; 
      public int  wParam; 
      public int  lParam; 
      public int  time; 
      public int  pt; 
     }; 

     [DllImport("kernel32.dll")] 
     public static extern int LoadLibrary(string dllToLoad); 

     public AppMonitor() 
     { 
     } 

     private int hHook; 
     private int hMod; 

     public event EventHandler AppClosing; 

     private unsafe delegate int GetMsgProcDelegate(int code, int wParam, void* lParam); 
     private unsafe GetMsgProcDelegate m_dlgt; 

     private unsafe int GetMsgProc(int code, int wParam, void* lParam) 
     { 
      if (code != HC_ACTION || wParam != PM_REMOVE) 
       return CallNextHookEx(this.hHook, code, wParam, lParam); 

      Msg* msg = (Msg*)lParam; 

      //if (msg.message == WM_QUIT) 
      // OnAppClosing(new EventArgs()); 

      return CallNextHookEx(this.hHook, code, wParam, lParam); 
     } 

     protected virtual void OnAppClosing(EventArgs e) 
     { 
      EventHandler h = AppClosing; 
      if (h != null) 
      { 
       h(this, e); 
      } 
     } 

     public unsafe bool setHook(int hWnd) 
     { 
      hMod = LoadLibrary("AppMonitor.dll"); //this dll 
      int procId = 0; 

      int threadId = GetWindowThreadProcessId(hWnd, out procId); 
      if (threadId == 0) 
       throw new System.Exception("Invalid thread Id"); 

      m_dlgt = GetMsgProc; 
      this.hHook = SetWindowsHookEx(WH_GETMESSAGE, m_dlgt, hMod, threadId); 

      if (this.hHook == 0) 
       throw new System.Exception("Hook not successfull! Error code: " + GetLastError()); 

      return this.hHook != 0; 
     } 

     public bool unSetHook() 
     { 
      bool result = false; 
      if (hHook != 0) 
       result = UnhookWindowsHookEx(hHook); 
      return result; 
     } 
    } 
} 
+0

在同一臺計算機上的進程? – jglouie

+0

使用[消息鉤子](http://stackoverflow.com/questions/9665579/setting-up-hook-on-windows-messages)並查找WM_CLOSE消息,或設置一個計時器來輪詢其他窗口是否處理離開舉辦活動。 –

+0

是的,這些進程在同一臺機器上。 – kozolika

回答

0

不,這不能用反射來完成。

您提供的信息很少給出一個明確的答案...例如:

  • 如果你有兩個進程「正在開發」(即可以更改包括源代碼),那麼解決辦法可能是易
    否則就變得複雜和潛在不可靠

  • 如果這兩個過程是在同一臺機器上,則有可能通過掛鉤
    否則,你將需要一個更復雜的實現。

  • 如果你只是想以被通知的形式關閉,然後將其可能
    如果你想在另一個進程的上下文中執行的東西,甚至處理該事件自己,這是非常複雜的,這取決於究竟是什麼你想它可能是不可能的...

請提供更多的細節,以便有可能的具體答案。

+0

是的,這兩個過程都在開發中。 – kozolika

+0

你仍然需要給予更多的細節......究竟是你的目標? – Yahia

+0

更多的datails添加到問題描述 – kozolika

1

如果你能以某種方式找到您要監視的進程(通過窗口的標題,或如下面的例子中,通過「友好」的進程名),很容易監控它關閉。

下面的例子演示瞭如何監控「記事本」程序,看看當它關閉:

using System; 
using System.Diagnostics; 

// To test this program: 
// (1) Start Notepad. 
// (2) Run this program. 
// (3) Close Notepad. 
// (4) This program should print "Notepad exited". 

namespace Demo 
{ 
    internal class Program 
    { 
     public static void Main(string[] args) 
     { 
      foreach (var process in Process.GetProcessesByName("notepad")) 
      { 
       Console.WriteLine("Found a Notepad process to attach to."); 
       process.EnableRaisingEvents = true; 
       process.Exited += process_Exited; 
      } 

      Console.WriteLine("Press ENTER to quit."); 
      Console.ReadLine(); 
     } 

     private static void process_Exited(object sender, EventArgs e) 
     { 
      Console.WriteLine("Notepad exited."); 
     } 
    } 
} 

如果需要,你可以使用Process.GetProcesses()來枚舉計算機上的所有進程,併爲每一個檢查Process.MainWindowTitle,看看你是否已經找到你想要的。

+0

是否有可能得到某種方式的過程中的主要形式(或任何形式的)?然後訂閱FormClosing事件? – kozolika

+0

不,你不能這樣做。但如果關閉主窗體也會關閉應用程序,那麼您將能夠檢測到該問題。 –

+0

非常酷,我從來不知道你可以使用Process類來查看來自其他進程的事件。 –