以前使用C++開發的version.dll文件,由於各個用戶環境的不同,造成某些用戶加載不了我們開發的插件,並且寫version.dll的同事還沒找到好的解決辦法,所以得換一種思路去解決這個問題,就是Lync啓動時加載我們的插件。
因此寫了一個winform程序來監控進程的變化,這個程序還要設置爲開機啓動。下面是主要代碼:
1 static class Program 2 { 3 public static System.Threading.Mutex _run; 4 /// <summary> 5 /// 應用程序的主入口點。 6 /// </summary> 7 [STAThread] 8 static void Main() 9 { 10 bool noRun = false; 11 _run = new System.Threading.Mutex(true, "ICOLyncWindow", out noRun); 12 if (noRun) 13 { 14 _run.ReleaseMutex(); 15 try 16 { 17 //處理未捕獲的異常 18 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 19 //處理UI線程異常 20 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 21 //處理非UI線程異常 22 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 23 24 Application.EnableVisualStyles(); 25 Application.SetCompatibleTextRenderingDefault(false); 26 Application.Run(new IcoLyncForm()); 27 } 28 catch (Exception ex) 29 { 30 Logger.Error(ex); 31 } 32 } 33 } 34 35 static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) 36 { 37 Logger.Error(e.Exception); 38 } 39 40 static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 41 { 42 Logger.Error(e.ExceptionObject as Exception); 43 } 44 }
1 public partial class IcoLyncForm : Form 2 { 3 [DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)] 4 static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow); 5 [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] 6 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 7 8 public IcoLyncForm() 9 { 10 InitializeComponent(); 11 this.Load += new EventHandler(Form1_Load); 12 } 13 14 void Form1_Load(object sender, EventArgs e) 15 { 16 Process[] p = Process.GetProcessesByName("lync"); 17 if (p.Length > 0) 18 { 19 lyncnet.clsLyncNet cls = new lyncnet.clsLyncNet(); 20 this.Invoke(new Action(() => { cls.NetMain(); })); 21 } 22 23 //創建WQL事件查詢,用於實例創建 24 var qCreate = new WqlEventQuery("__InstanceCreationEvent", 25 TimeSpan.FromSeconds(1), //WHTHIN = 1 26 "TargetInstance ISA 'Win32_Process'"); 27 //創建WQL事件查詢,用於實例刪除 28 var qDelete = new WqlEventQuery("__InstanceDeletionEvent", 29 TimeSpan.FromSeconds(1), //WHTHIN = 1 30 "TargetInstance ISA 'Win32_Process'"); 31 32 //創建事件查詢的偵聽器(ManagementEventWatcher) 33 var wCreate = new ManagementEventWatcher(qCreate); 34 var wDelete = new ManagementEventWatcher(qDelete); 35 36 wCreate.EventArrived += new EventArrivedEventHandler(wCreate_EventArrived); 37 wDelete.EventArrived += new EventArrivedEventHandler(wDelete_EventArrived); 38 39 //異步開始偵聽 40 wCreate.Start(); 41 wDelete.Start(); 42 43 IntPtr intptr; 44 try 45 { 46 do 47 { 48 intptr = FindWindow(null, "ICOLync"); 49 if (intptr != IntPtr.Zero) 50 { 51 ShowWindow(intptr, 0); 52 } 53 } 54 while (intptr == IntPtr.Zero); 55 IcoLync.Util.RegistryHelper.RunWhenStart(true, "ICOLync", AppDomain.CurrentDomain.BaseDirectory + "ICOLync.exe"); 56 } 57 catch (Exception ex) 58 { 59 Logger.Error(ex); 60 } 61 } 62 63 //輸出事件對應的ManagementBaseObject(本例中的Win32_Process實例)的信息 64 static string GetInfo(ManagementBaseObject mobj) 65 { 66 var instance = (ManagementBaseObject)mobj["TargetInstance"]; 67 return instance["Name"].ToString(); 68 } 69 70 void wCreate_EventArrived(object sender, EventArrivedEventArgs e) 71 { 72 if (GetInfo(e.NewEvent).Equals("lync.exe")) 73 { 74 lyncnet.clsLyncNet cls = new lyncnet.clsLyncNet(); 75 this.Invoke(new Action(() => { cls.NetMain(); })); 76 } 77 } 78 79 void wDelete_EventArrived(object sender, EventArrivedEventArgs e) 80 { 81 if (GetInfo(e.NewEvent).Equals("lync.exe")) this.RestartMe(); 82 } 83 84 private void RestartMe() 85 { 86 Program._run.Close(); 87 Process.Start(Application.ExecutablePath); 88 Process.GetCurrentProcess().Kill(); 89 } 90 }
這個winform程序啓動之後調用win32 api隱藏起來。檢測到新增Lync.exe進程時,註冊ICOLync插件,Lync.exe進程註銷後,重啓winform程序。開始還考慮把winform程序的進程保護起來,很麻煩,不同的操作系統,出現的狀況還不一樣,所以取消了。
2013.7.26修改:
使用System.Threading.Mutex互斥體,實現程序只啓動單一進程,發現有一個Bug,在windows多用戶的情況下,每一個用戶都可以啓動一個進程,所以要保持整天計算機只啓動一個進程,應改爲如下: