2017-03-01 92 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

相關問題