首页 > 代码库 > 多次单击快捷方式,只运行一个程序实例
多次单击快捷方式,只运行一个程序实例
在应用程序安装之后,单击一次快捷方式,就运行一个程序实例,对于资源独占型程序来说,这样是不可以的,比如该程序使用了当前系统的某个端口,当同样的程序再次运行,再次试图占用同一个端口次,会提示“端口已经被占用的”异常。如此,必须在启动应用程序时,必须判断该程序是否已经有一个实例在运行。下面这个类中先判断该程序的实例有没有在运行,使用线程同步类EventWaitHandle(Boolean, EventResetMode, String)及注册正在等待 WaitHandle 的委托方法RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int64, Boolean)来进行线程间同步。
public class WpfSingleInstance
{
public static Window handelWin
{
private get;
set;
}
private static bool findIfAlreadyRun()
{
try
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") ==
current.MainModule.FileName)
{
return true;
}
}
}
}
catch (Exception ex)
{
new SaveExceptionInfo().SaveLogAsTXTInfoex(ex.Message);
}
return false;
}
//线程间同步
internal static void Make(String name, Application app)
{
EventWaitHandle eventWaitHandle = null;
String eventName = Environment.MachineName + "-" + Environment.CurrentDirectory.Replace(‘\\‘, ‘-‘) + "-" + name;
bool isFirstInstance = !findIfAlreadyRun();
if (isFirstInstance)
{
try
{
//当前程序没有实例在运行时
eventWaitHandle = new EventWaitHandle(
false,
EventResetMode.AutoReset,
eventName);
ThreadPool.RegisterWaitForSingleObject(eventWaitHandle, waitOrTimerCallback,app, Timeout.Infinite, false);
}
catch (Exception ex)
{
new SaveExceptionInfo().SaveLogAsTXTInfoex(ex.Message);
}
finally
{
eventWaitHandle.Close();
}
}
else
{
try
{
//当前程序已经有了实例在运行时,打开已经运行的实例,而不是从新运行一个
eventWaitHandle = EventWaitHandle.OpenExisting(eventName);
//唤醒已经运行的实例
eventWaitHandle.Set();
// For that exit no interceptions
Environment.Exit(0);
}
catch (Exception ex)
{
new SaveExceptionInfo().SaveLogAsTXTInfoex(ex.Message);
}
}
}
/// < summary>
/// 已经在运行的程序实例在被唤醒时的需要执行的代码
/// < /summary>
/// <param name="state"></param>
/// <param name="timedOut"></param>
private static void waitOrTimerCallback(Object state, Boolean timedOut)
{
Application app = (Application)state;
app.Dispatcher.BeginInvoke(new activate(delegate()
{
// Application.Current.MainWindow.Activate();
//if (handelWin != null)
//{
// handelWin.Show();
//}
//else
//{
Application.Current.MainWindow.Activate();
//}
}), null);
}
private delegate void activate();
}
在App.xaml.cs中重载OnStartup方法,调用WpfSingleInstance
protected override void OnStartup(StartupEventArgs e) { WpfSingleInstance.Make("FilePullar", this); base.OnStartup(e); }
这样单击已运行程序的快捷方式时,会弹出已经在运行的应用程序的界面,而不是重新打开应用程序的实例。