所谓单实例应用程序就是只能开启一个进程的应用程序,通常未做处理的WPF程序可以多次点击exe程序,每次点击,系统都会分配一个进程。这样不仅造成了资源的浪费还会导致其他各种问题,例如,我们的程序里面寄宿了一个WCF接口,那多次启动会导致端口绑定错误。为了让大家对此有个更加深刻的印象,下面做个简单的演示。
1、创建一个简单的WPF应用程序,没做任何处理。如下图所示:
2、不采用调试模式,打开项目根目录下的bin/Debug,直接点击WPF.SimpleApp.exe运行程序,可以看到程序正常运行,那么现在试试点击多次,然后打开任务管理器,看看。如下图:
结果就是,我打开了三个WPF.SimpleApp.exe,同时存在三个WPF.SimpleApp.exe进程。
好了,现在要做的就是做个限制,无论用户点击多少次,始终运行一个exe,同时只能存在一个exe进程。废话不多说,下面进入正题。
在这之前,因为本人还是比较喜欢winform的启动方式,因此我把创建项目时自动生成的App.xaml删除,新增了个Program.cs文件,代码如下:
usingSystem;usingSystem.Windows;namespaceWPF.SimpleApp
{classProgram
{
[STAThread]static void Main(string[] args)
{
Application app= newApplication();
MainWindow win= newMainWindow();
app.Run(win);
}
}
}
说明:WPF的启动方式不止这一种,感兴趣的可以自行百度。
下面进入正题
1、使用System.Threading.Mutex,Mutex是一个同步基元,也可用于进程间同步。代码如下:
usingSystem;usingSystem.Windows;namespaceWPF.SimpleApp
{classProgram
{const string GlobalMutexName = "WPF.SimpleApp.Mutex";
[STAThread]static void Main(string[] args)
{
System.Threading.Mutex mutex= null;bool isExists = System.Threading.Mutex.TryOpenExisting(GlobalMutexName,outmutex);if(isExists && null !=mutex)
{//表示互斥体已经存在,即已经打开了一个程序,这里提示用户
MessageBox.Show("程序已经在运行");return;
}else{//否则创建新的互斥体
mutex = new System.Threading.Mutex(true, GlobalMutexName);
}
Application app= newApplication();
MainWindow win= newMainWindow();
app.Run(win);//程序关闭,记得释放所占用资源
if (null !=mutex)
{
mutex.Dispose();
}
}
}
}
运行效果:
可以看到,当打开一个应用程序之后,再次点击exe,会提示“程序已经在运行”。关闭程序之后,再次打开(第一次正常,之后提示一样)。
2、使用Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase包装。
首先添加对程序集:Microsoft.VisualBasic 的引用,如下图:
然后添加一个SingleWarpInstanceApp类,并继承Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase类,然后重新方法OnStartup和OnStartupNextInstance。
实现如下:
public classSingleWarpInstanceApp : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{publicSingleWarpInstanceApp()
{this.IsSingleInstance = true;
}protected override boolOnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
{
Application app= newApplication();
MainWindow win= newMainWindow();
app.Run(win);bool tag = base.OnStartup(eventArgs);returntag;
}protected override voidOnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
{
MessageBox.Show("程序已经在运行");
}
}
在Program启动方法里面加上如下代码:
SingleWarpInstanceApp app = newSingleWarpInstanceApp();
app.Run(args);
运行效果一样。
最后贴上Program.cs的代码:
usingSystem;usingSystem.Windows;namespaceWPF.SimpleApp
{classProgram
{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= newSingleWarpInstanceApp();
app.Run(args);#endregion}
}public classSingleWarpInstanceApp : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{publicSingleWarpInstanceApp()
{this.IsSingleInstance = true;
}protected override boolOnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
{
Application app= newApplication();
MainWindow win= newMainWindow();
app.Run(win);bool tag = base.OnStartup(eventArgs);returntag;
}protected override voidOnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
{
MessageBox.Show("程序已经在运行");
}
}
}
至此,完毕。