所谓单实例应用程序就是只能开启一个进程的应用程序,通常未做处理的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("程序已经在运行");
}
}
}
至此,完毕。