首页 > 代码库 > 多次单击快捷方式,只运行一个程序实例

多次单击快捷方式,只运行一个程序实例

在应用程序安装之后,单击一次快捷方式,就运行一个程序实例,对于资源独占型程序来说,这样是不可以的,比如该程序使用了当前系统的某个端口,当同样的程序再次运行,再次试图占用同一个端口次,会提示“端口已经被占用的”异常。如此,必须在启动应用程序时,必须判断该程序是否已经有一个实例在运行。下面这个类中先判断该程序的实例有没有在运行,使用线程同步类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);
                }

 

这样单击已运行程序的快捷方式时,会弹出已经在运行的应用程序的界面,而不是重新打开应用程序的实例。