App.xaml.cs中的代碼每次都差不多,故特地將其整理出來直接復用: ...
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 }