2017-03-01 93 views
1

我想让它如此,如果我的程序的另一个实例正在运行,它应该关闭已运行的实例并启动新实例。我目前试过这样:如果程序正在运行,杀死其他实例?

[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; 
     } 
    } 
} 

但由于某些原因,它不杀已经运行的情况下,它只是杀死自己的大部分时间,有时它不会做任何事情。

我该如何做到这一点?

编辑:我知道这样做是显示该应用程序已在运行的消息的常用方法,但在这种应用中,它杀死了老工艺而不是显示一个消息是至关重要的。

+0

那么你是说当你正在调试时它碰到'proc.Kill();'语句,它不会导致进程被终止? –

+2

我认为你只是不想开始新的实例,而不是从一个已经执行的实例下拉开地毯。您可以向用户显示一条消息,然后关闭以清楚表明它无法启动....除非您不关心其他应用程序实例在做什么(将某些内容保存到某个商店,请求,用户做某事等)。也考虑可能的终端服务器含义......(承载多个同时登录的服务器)。 – Igor

+2

你的确意识到* common *模式是为了让新实例关闭而转换旧的(转移了任何参数/将旧参数带到前面)。让用户以其他方式采取行动会让你感到非常惊讶。 –

回答

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 \”描述了互斥体名称相对于终端服务器会话的范围,而不是相对于进程。

+0

Omg这实际上有效!但是,还有一个单一的问题。如果有人重命名可执行文件,它仍然会运行2个实例。我该如何反击?不过,非常感谢您的回答! –

+0

它不会运行,它会尝试查找并杀死旧的进程,但不会找到具有相同名称的进程。 (也许应该有一些限制 - 只检查一次所有进程。)直到获得互斥体后才会显示表单。 – fofik

相关问题