App.xaml.cs中的代码每次都差不多,故特地将其整理出来直接复用:
5 using System; 6 using System.Configuration; 7 using System.Diagnostics; 8 using System.Globalization; 9 using System.Net; 10 using System.Net.Sockets; 11 using System.Reflection; 12 using System.Runtime.InteropServices; 13 using System.Windows; 14 15 namespace WpfDemo 16 { 17 /// <summary> 18 /// App.xaml 的交互逻辑 19 /// </summary> 20 public partial class App : Application 21 { 22 private LoginWindow login = new LoginWindow(); 23 private ILog logger; 24 25 static App() 26 { 27 log4net.Config.XmlConfigurator.Configure(); 28 } 29 30 public App() 31 { 32 logger = LogManager.GetLogger(typeof(this)); 33 } 34 35 System.Threading.Mutex _mutex; 36 protected override void OnStartup(StartupEventArgs e) 37 { 38 Assembly assembly = Assembly.GetExecutingAssembly(); 39 string mutexName = string.Format(CultureInfo.InvariantCulture, "Local\\{{{0}}}{{{1}}}", assembly.GetType().GUID, assembly.GetName().Name); 40 bool ret = false; 41 _mutex = new System.Threading.Mutex(true, mutexName, out ret); 42 if (!ret) 43 { 44 this.logger.Info("已经运行程序,激活至主窗口."); 45 HandleRunningInstance(); 46 Environment.Exit(0); 47 return; 48 } 49 50 base.OnStartup(e); 51 this.logger.Info("App startup."); 52 this.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown; 53 54 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 55 this.DispatcherUnhandledException += App_DispatcherUnhandledException; 56 57 this.login.Show(); 58 } 59 60 void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 61 { 62 try 63 { 64 var exception = e.ExceptionObject as Exception; 65 if (exception != null) 66 { 67 this.logger.FatalFormat("非UI线程全局异常, Message:{0}, Error: {1}", exception.Message, exception.ToString()); 68 } 69 } 70 catch (Exception ex) 71 { 72 this.logger.FatalFormat("非UI线程全局异常, Message:{0}, Error: {1}", ex.Message, ex.ToString()); 73 } 74 } 75 76 void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) 77 { 78 try 79 { 80 e.Handled = true; 81 this.logger.FatalFormat("UI线程全局异常:Meassage:{0}, Error: {1}", e.Exception.Message, e.Exception.ToString()); 82 } 83 catch (Exception ex) 84 { 85 this.logger.FatalFormat("UI线程全局异常:Meassage:{0}, Error: {1}", ex.Message, ex.ToString()); 86 } 87 } 88 89 90 protected override void OnExit(ExitEventArgs e) 91 { 92 this.logger.Info("App exit."); 93 94 base.OnExit(e); 95 } 96 97 ///<summary> 98 /// 该函数设置由不同线程产生的窗口的显示状态 99 /// </summary> 100 /// <param name="hWnd">窗口句柄</param> 101 /// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分</param> 102 /// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零</returns> 103 [DllImport("User32.dll")] 104 private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); 105 106 /// <summary> 107 /// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。 108 /// 系统给创建前台窗口的线程分配的权限稍高于其他线程。 109 /// </summary> 110 /// <param name="hWnd">将被激活并被调入前台的窗口句柄</param> 111 /// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零</returns> 112 [DllImport("User32.dll")] 113 private static extern bool SetForegroundWindow(IntPtr hWnd); 114 115 static Process RunningInstance() 116 { 117 Process current = Process.GetCurrentProcess(); 118 Process[] processes = Process.GetProcessesByName(current.ProcessName); 119 foreach (Process process in processes) 120 { 121 if (process.Id != current.Id) 122 { 123 if (process.MainModule.FileName == current.MainModule.FileName) 124 { 125 return process; 126 } 127 } 128 } 129 return null; 130 } 131 132 private const int SW_NORMAL = 1; //正常弹出窗体 133 private const int SW_MAXIMIZE = 3; //最大化弹出窗体 134 135 public static void HandleRunningInstance() 136 { 137 var instance = RunningInstance(); 138 if (instance != null) 139 { 140 ShowWindowAsync(instance.MainWindowHandle, SW_NORMAL); 141 SetForegroundWindow(instance.MainWindowHandle); 142 } 143 } 144 } 145 }