所謂單實例應用程序就是只能開啟一個進程的應用程序,通常未做處理的WPF程序可以多次點擊exe程序,每次點擊,系統都會分配一個進程。這樣不僅造成了資源的浪費還會導致其他各種問題,例如,我們的程序里面寄宿了一個WCF接口,那多次啟動會導致端口綁定錯誤。為了讓大家對此有個更加深刻的印象,下面做個簡單的演示。
1、創建一個簡單的WPF應用程序,沒做任何處理。如下圖所示:
2、不采用調試模式,打開項目根目錄下的bin/Debug,直接點擊WPF.SimpleApp.exe運行程序,可以看到程序正常運行,那么現在試試點擊多次,然后打開任務管理器,看看。如下圖:
結果就是,我打開了三個WPF.SimpleApp.exe,同時存在三個WPF.SimpleApp.exe進程。
好了,現在要做的就是做個限制,無論用戶點擊多少次,始終運行一個exe,同時只能存在一個exe進程。廢話不多說,下面進入正題。
在這之前,因為本人還是比較喜歡winform的啟動方式,因此我把創建項目時自動生成的App.xaml刪除,新增了個Program.cs文件,代碼如下:
using System; using System.Windows; namespace WPF.SimpleApp { class Program { [STAThread] static void Main(string[] args) { Application app = new Application(); MainWindow win = new MainWindow(); app.Run(win); } } }
說明:WPF的啟動方式不止這一種,感興趣的可以自行百度。
下面進入正題
1、使用System.Threading.Mutex,Mutex是一個同步基元,也可用於進程間同步。代碼如下:
using System; using System.Windows; namespace WPF.SimpleApp { class Program { const string GlobalMutexName = "WPF.SimpleApp.Mutex"; [STAThread] static void Main(string[] args) { System.Threading.Mutex mutex = null; bool isExists = System.Threading.Mutex.TryOpenExisting(GlobalMutexName,out mutex); if(isExists && null != mutex) { //表示互斥體已經存在,即已經打開了一個程序,這里提示用戶 MessageBox.Show("程序已經在運行"); return; } else { //否則創建新的互斥體 mutex = new System.Threading.Mutex(true, GlobalMutexName); } Application app = new Application(); MainWindow win = new MainWindow(); app.Run(win); //程序關閉,記得釋放所占用資源 if (null != mutex) { mutex.Dispose(); } } } }
運行效果:
可以看到,當打開一個應用程序之后,再次點擊exe,會提示“程序已經在運行”。關閉程序之后,再次打開(第一次正常,之后提示一樣)。
2、使用Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase包裝。
首先添加對程序集:Microsoft.VisualBasic 的引用,如下圖:
然后添加一個SingleWarpInstanceApp類,並繼承Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase類,然后重新方法OnStartup和OnStartupNextInstance。
實現如下:
public class SingleWarpInstanceApp : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase { public SingleWarpInstanceApp() { this.IsSingleInstance = true; } protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs) { Application app = new Application(); MainWindow win = new MainWindow(); app.Run(win); bool tag = base.OnStartup(eventArgs); return tag; } protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs) { MessageBox.Show("程序已經在運行"); } }
在Program啟動方法里面加上如下代碼:
SingleWarpInstanceApp app = new SingleWarpInstanceApp(); app.Run(args);
運行效果一樣。
最后貼上Program.cs的代碼:
using System; using System.Windows; namespace WPF.SimpleApp { class Program { const string GlobalMutexName = "WPF.SimpleApp.Mutex"; [STAThread] static void Main(string[] args) { #region 第一種方法 //System.Threading.Mutex mutex = null; //bool isExists = System.Threading.Mutex.TryOpenExisting(GlobalMutexName, out mutex); //if (isExists && null != mutex) //{ // //表示互斥體已經存在,即已經打開了一個程序,這里提示用戶 // MessageBox.Show("程序已經在運行"); // return; //} //else //{ // //否則創建新的互斥體 // mutex = new System.Threading.Mutex(true, GlobalMutexName); //} //Application app = new Application(); //MainWindow win = new MainWindow(); //app.Run(win); ////程序關閉,記得釋放所占用資源 //if (null != mutex) //{ // mutex.Dispose(); //} #endregion #region 第二種方法 SingleWarpInstanceApp app = new SingleWarpInstanceApp(); app.Run(args); #endregion } } public class SingleWarpInstanceApp : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase { public SingleWarpInstanceApp() { this.IsSingleInstance = true; } protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs) { Application app = new Application(); MainWindow win = new MainWindow(); app.Run(win); bool tag = base.OnStartup(eventArgs); return tag; } protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs) { MessageBox.Show("程序已經在運行"); } } }
至此,完畢。