以前使用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多用户的情况下,每一个用户都可以启动一个进程,所以要保持整天计算机只启动一个进程,应改为如下: