如果程序正在运行,请杀死其他实例?

时间:2017-03-01 13:26:50

标签: c# instance mutex kill multiple-instances

我正在努力使其如果我的程序的另一个实例正在运行,它应该关闭已经运行的实例并启动新实例。我目前试过这个:

[STAThread]
static void Main()
{
    Mutex mutex = new System.Threading.Mutex(false, "supercooluniquemutex");
    try
    {
        if (mutex.WaitOne(0, false))
        {
            // Run the application
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new fMain());
        }
        else
        {
            foreach (Process proc in Process.GetProcesses())
            {
                if (proc.ProcessName.Equals(Process.GetCurrentProcess().ProcessName) && proc.Id != Process.GetCurrentProcess().Id)
                {
                    proc.Kill();
                    break;
                }
            }
            // Run the application
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new fMain());
        }
    }
    finally
    {
        if (mutex != null)
        {
            mutex.Close();
            mutex = null;
        }
    }
}

但由于某些原因,它并没有杀死已经运行的实例,它只会在大部分时间内自杀,有时它根本不会做任何事情。

我该怎么做才能让它发挥作用?

编辑:我知道通常的做法是显示应用程序已在运行的消息,但在此应用程序中,它必须杀死旧进程而不是显示消息。

1 个答案:

答案 0 :(得分:2)

首先,您需要在杀死上一个进程后再次等待互斥锁。当你那样你会得到AbandonedMutexException。有关please check this link的详细信息,我假设在该异常之后可以继续。

你可以试试。

Mutex mutex = new System.Threading.Mutex(false, "supercooluniquemutex");
        try
        {
            bool tryAgain = true;
            while (tryAgain)
            {
                bool result = false;
                try
                {
                    result = mutex.WaitOne(0, false);
                }
                catch (AbandonedMutexException ex)
                {
                    // No action required
                    result = true;
                }
                if (result)
                {
                    // Run the application
                    tryAgain = false;
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new fMain());
                }
                else
                {
                    foreach (Process proc in Process.GetProcesses())
                    {
                        if (proc.ProcessName.Equals(Process.GetCurrentProcess().ProcessName) && proc.Id != Process.GetCurrentProcess().Id)
                        {
                            proc.Kill();
                            break;
                        }
                    }
                    // Wait for process to close
                    Thread.Sleep(2000);
                }
            }
        }
        finally
        {
            if (mutex != null)
            {
                mutex.Close();
                mutex = null;
            }
        }

在该示例中,如果我得到AbandonedMutexException,我获得了mutext的所有权,可以继续。

此外,您使用本地Mutex,另一个用户可以在另一个终端服务器会话下运行相同的应用程序。 MSDN says

  

在运行终端服务的服务器上,命名系统互斥锁可以具有两个级别的可见性。如果其名称以前缀“Global \”开头,则互斥锁在所有终端服务器会话中都可见。如果其名称以前缀“Local \”开头,则互斥锁仅在创建它的终端服务器会话中可见。在这种情况下,服务器上的每个其他终端服务器会话中可以存在具有相同名称的单独互斥锁。如果在创建命名互斥锁时未指定前缀,则它将使用前缀“Local \”。在终端服务器会话中,名称仅由其前缀不同的两个互斥锁是单独的互斥锁,并且两者对终端服务器会话中的所有进程都可见。也就是说,前缀名称“Global \”和“Local \”描述互斥体名称相对于终端服务器会话的范围,而不是相对于进程。