2009-05-04 4 views
19

Per consentire solo una singola istanza di un'applicazione in esecuzione sto usando mutex. Il codice è riportato di seguito. È questo il modo giusto per farlo? Ci sono dei difetti nel codice?Esegui una singola istanza di un'applicazione utilizzando Mutex

Come visualizzare l'applicazione già in esecuzione quando l'utente tenta di aprire l'applicazione la seconda volta. Al momento (nel codice qui sotto), sto semplicemente visualizzando un messaggio che un'altra istanza è già in esecuzione.

static void Main(string[] args) 
    { 
     Mutex _mut = null; 

     try 
     { 
      _mut = Mutex.OpenExisting(AppDomain.CurrentDomain.FriendlyName); 
     } 
     catch 
     { 
      //handler to be written 
     } 

     if (_mut == null) 
     { 
      _mut = new Mutex(false, AppDomain.CurrentDomain.FriendlyName); 
     } 
     else 
     { 
      _mut.Close(); 
      MessageBox.Show("Instance already running"); 

     }    
    } 
+0

duplicati di http://stackoverflow.com/questions/646480/is-using-a-mutex-to-prevent-multipule -instances-of-the-same-program-from-running –

+0

Assicurati di leggere questo: http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global -mutex-in-c/229567 –

risposta

8

ho fatto in questo modo, una volta, spero che aiuta:

bool createdNew; 

Mutex m = new Mutex(true, "myApp", out createdNew); 

if (!createdNew) 
{ 
    // myApp is already running... 
    MessageBox.Show("myApp is already running!", "Multiple Instances"); 
    return; 
} 
+18

Questo codice non è sicuro o corretto: http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in -c/229567 –

+2

Vorrei che questo fosse sicuro e corretto. È molto semplice e può essere facilmente scritto senza quasi nessun pensiero lol. +1 a entrambi, però. –

+0

Questo codice funziona nel codice di debug ma non nel rilascio exe !!! –

1

Partenza il codice di esempio riportato sul this page

In breve, si utilizza il Mutex sovraccarico ctor(bool, string, out bool) che ti dice tramite un parametro out, se hai la proprietà del mutex denominato. Se si è la prima istanza, questo parametro out conterrà true dopo la chiamata del ctor, nel qual caso si procederà come al solito. Se questo parametro è falso, significa che un'altra istanza ha già ottenuto la proprietà/è in esecuzione, nel qual caso viene visualizzato un messaggio di errore "Un'altra istanza è già in esecuzione." e poi esci con grazia.

7
static void Main() 
{ 
    using(Mutex mutex = new Mutex(false, @"Global\" + appGuid)) 
    { 
    if(!mutex.WaitOne(0, false)) 
    { 
     MessageBox.Show("Instance already running"); 
     return; 
    } 

    GC.Collect();     
    Application.Run(new Form1()); 
    } 
} 

Fonte: http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx

+1

Questo codice non è sicuro o corretto ... http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567 –

+1

' Globale "lo rende globale per la macchina, non per l'utente corrente. Pertanto, in un ambiente server o su servizi terminal, solo un utente può eseguirlo alla volta. Credo che la maggior parte degli utenti si aspettino che una singola istanza indichi una singola istanza per loro. –

1

Io uso questo:

private static Mutex _mutex; 

    private static bool IsSingleInstance() 
    { 
     _mutex = new Mutex(false, _mutexName); 

     // keep the mutex reference alive until the normal 
     //termination of the program 
     GC.KeepAlive(_mutex); 

     try 
     { 
      return _mutex.WaitOne(0, false); 
     } 
     catch (AbandonedMutexException) 
     { 
      // if one thread acquires a Mutex object 
      //that another thread has abandoned 
      //by exiting without releasing it 

      _mutex.ReleaseMutex(); 
      return _mutex.WaitOne(0, false); 
     } 
    } 


    public Form1() 
    { 
     if (!isSingleInstance()) 
     { 
      MessageBox.Show("Instance already running"); 
      this.Close(); 
      return; 
     } 

     //program body here 
    } 

    private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     if (_mutex != null) 
     { 
      _mutex.ReleaseMutex(); 
     } 
    }  
1

Usa app con le impostazioni di timeout e di sicurezza. Ho usato la mia classe personalizzata:

private class SingleAppMutexControl : IDisposable 
    { 
     private readonly Mutex _mutex; 
     private readonly bool _hasHandle; 

     public SingleAppMutexControl(string appGuid, int waitmillisecondsTimeout = 5000) 
     { 
      bool createdNew; 
      var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), 
       MutexRights.FullControl, AccessControlType.Allow); 
      var securitySettings = new MutexSecurity(); 
      securitySettings.AddAccessRule(allowEveryoneRule); 
      _mutex = new Mutex(false, "Global\\" + appGuid, out createdNew, securitySettings); 
      _hasHandle = false; 
      try 
      { 
       _hasHandle = _mutex.WaitOne(waitmillisecondsTimeout, false); 
       if (_hasHandle == false) 
        throw new System.TimeoutException(); 
      } 
      catch (AbandonedMutexException) 
      { 
       _hasHandle = true; 
      } 
     } 

     public void Dispose() 
     { 
      if (_mutex != null) 
      { 
       if (_hasHandle) 
        _mutex.ReleaseMutex(); 
       _mutex.Dispose(); 
      } 
     } 
    } 

e usarlo:

private static void Main(string[] args) 
    { 
     try 
     { 
      const string appguid = "{xxxxxxxx-xxxxxxxx}"; 
      using (new SingleAppMutexControl(appguid)) 
      { 

       Console.ReadLine(); 
      } 
     } 
     catch (System.TimeoutException) 
     { 
      Log.Warn("Application already runned"); 
     } 
     catch (Exception ex) 
     { 
      Log.Fatal(ex, "Fatal Error on running"); 
     } 
    }