2010-12-06 4 views

Antwort

44

würde ich ein Mutex

static void Main() 
    { 
    string mutex_id = "MY_APP"; 
    using (Mutex mutex = new Mutex(false, mutex_id)) 
    { 
     if (!mutex.WaitOne(0, false)) 
     { 
      MessageBox.Show("Instance Already Running!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand); 
      return; 
     } 
     // Do stuff 
    } 
    } 
+1

Dank SwDevMan81 für Code-Schnipsel. –

+1

Kann dies auch auf eine bestimmte Anzahl von Instanzen beschränkt werden? –

+0

Danke. Ich verwende dies in einem WinForms-Projekt in VS2015. Ich habe das obige mit dem Main() in program.cs zusammengeführt, so dass der "// Do stuff" Speicherort diese 3 VS-generierten Zeilen hätte: "Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault (false); Application.Run (new Form1()); "Auch hinzugefügt" mit System.Threading; "an der Spitze von program.cs. – gus

18

Es gibt viele Möglichkeiten, verwendet, wie zum Beispiel -

  • Liste der Prozesse vor dem Start und die Inbetriebnahme zu leugnen, Aufzählen, wenn Prozessname ist bereits vorhanden.
  • Erstellen eines Mutex beim Start und Überprüfen, ob Mutex bereits existiert.
  • Starten eines Programms über eine Singleton-Klasse.

Jedes ist unter demoed:

http://iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx
http://www.codeproject.com/KB/cs/restricting_instances.aspx
http://www.codeproject.com/KB/cs/singleinstance.aspx

Jeder seine Vor- und Nachteile hat. Aber ich glaube, dass der erschaffende Mutex der beste ist.

+5

+1 für die Nicht - Mutex Alternativen –

31

Wenn Sie sich entscheiden, zu diesem Zweck einen Mutex zu verwenden, gibt es einige Gefahren sollten Sie beachten:

  • Wenn Sie die Anwendung auf eine Instanz pro Maschine (dh nicht eine pro angemeldet begrenzen möchten auf Benutzer), dann benötigen Sie Ihren Mutex-Namen, um mit dem Präfix Global\ zu beginnen. Wenn Sie dieses Präfix nicht hinzufügen, wird vom Betriebssystem für jeden Benutzer eine andere Instanz des Mutex erstellt.

  • Wenn Sie auf einem Win7/Vista-Rechner mit aktivierter Benutzerkontensteuerung arbeiten und die aktuelle Anwendungsinstanz zufällig als Administrator ausgeführt wird, können die nächsten Instanzen diese nicht erkennen, und Sie erhalten Berechtigungsausnahmen. Um dies zu vermeiden, müssen Sie beim Erstellen des Mutex einen anderen Satz von Berechtigungen angeben.

+6

Gute Fallstricke. Wenn Sie zwei Programme ausführen, die sich gegenseitig hassen, könnte einer von ihnen versuchen, einen Denial-of-Service-Angriff gegen den Benutzer zu starten, indem er den benannten Mutex des anderen Programms herausnimmt und ihn niemals freigibt. –

+3

Nice ... Aber ich bezweifle, dass es sich lohnt, davor zu schützen, da ein "böses" Programm, wenn man ihm einmal vertraut genug ist, andere Programme durcheinander bringen kann und den Mutex dafür nicht benötigt. Zum Beispiel kann es andere Prozesse töten, die installierten Programme anderer Programme beschädigen, seine Verknüpfungen ändern oder es komplett deinstallieren ... – Ran

+0

@Ran: Sicher, das ist in gewisser Weise einer von Raymond Chens "Du bist schon hinter der luftdichten Luke " Probleme. Die Berechtigungen, die erforderlich sind, um einen Mutex zu entfernen, unterscheiden sich jedoch möglicherweise von der Berechtigungsstufe, die erforderlich ist, um diese anderen Dinge auszuführen, die alle vollständige Vertrauenswürdigkeit erfordern. Ich weiß nicht, ob teilweise vertrauenswürdige Programme benannte Mutexe entfernen dürfen oder nicht; es wäre interessant, das herauszufinden. –

2

hier ist eine Lösung, die für mich

private static bool AlreadyRunning() 
{ 
    Process[] processes = Process.GetProcesses(); 
    Process currentProc = Process.GetCurrentProcess(); 

    foreach (Process process in processes) 
    { 
     try 
     { 
      if (process.Modules[0].FileName == System.Reflection.Assembly.GetExecutingAssembly().Location 
         && currentProc.Id != process.Id) 
       return true; 
     } 
     catch (Exception) 
     { 

     } 
    } 

    return false; 
} 

arbeitete ich die Ausgabe dieses Verfahren beim Programmstart dann überprüfen.

+0

Auf .net Kern (mindestens Linux) scheint es zu prüfen, ob process.Modules.Count> 0. Besser, Ausnahmen zu verhindern, sie dann passieren zu lassen und richtig zu ignorieren? – Theyouthis

2

Diese Antwort hinzufügen, weil die vorherigen nicht auf Linux (Ubuntu 14.0.4 getestet) mit .net core1.1 funktioniert haben und weil diese Frage in den Suchergebnissen hoch ist. Variante von @ MusuNajis Lösung, wenn es Ihnen nicht schon klar war. Single instance dotnetcore cli app on linux

0

Die Straight-Forward-Antwort für mich, weiter unten, von Madhur Ahuja Link (http://www.webskaper.no/wst/creatingasingleinstanceapplicationinc-aspx/) geschrieben genommen - hier wiedergegeben:

private static bool AlreadyRunning() 
    { 
     Process[] processes = Process.GetProcesses(); 
     Process currentProc = Process.GetCurrentProcess(); 
     logger.LogDebug("Current proccess: {0}", currentProc.ProcessName); 
     foreach (Process process in processes) 
     { 
      if (currentProc.ProcessName == process.ProcessName && currentProc.Id != process.Id) 
      { 
       logger.LogInformation("Another instance of this process is already running: {pid}", process.Id); 
       return true; 
      } 
     } 
     return false; 
    } 

Diese Antwort auf meine Dotnet Kern spezifische Frage ist auch hier gepostet (Die Code-Projekt-Lösungen wurden von mir versteckt).

Der wichtige Punkt war, den Mutex zu halten, bis der Prozess abgeschlossen ist (offensichtlich, denke ich).

bool createdNew; 
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew)) 
{ 
    if (createdNew) { 
     // process 
    } 
    else { 
     // in my case, quietly exit 
    } 
} 
Verwandte Themen