2009-05-04 16 views
19

Para permitir que se ejecute solo una instancia de una aplicación, estoy usando mutex. El código se da a continuación. ¿Esta es la manera correcta de hacerlo? ¿Hay algún defecto en el código?Ejecutar una instancia única de una aplicación utilizando Mutex

Cómo mostrar la aplicación que ya se está ejecutando cuando el usuario intenta abrir la aplicación por segunda vez. Actualmente (en el código a continuación), solo estoy mostrando un mensaje de que ya se está ejecutando otra instancia.

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

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

+0

Asegúrese de leer esto: http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global -mutex-in-c/229567 –

Respuesta

8

lo hice esta manera una vez, espero que ayude:

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

Este código no es seguro ni correcto: http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in -c/229567 –

+2

Ojalá fuera seguro y correcto. Es muy simple y se puede escribir fácilmente sin apenas pensarlo jajaja. +1 a los dos, sin embargo. –

+0

Este código funciona en el código de depuración pero no en el release exe !!! –

1

Salida del ejemplo de código se muestra en this page

En resumen, se utiliza el mutex sobrecarga ctor(bool, string, out bool) que le dice a través de un parámetro de salida, si usted tiene la propiedad de la exclusión mutua con nombre. Si es la primera instancia, este parámetro externo contendrá verdadero después de que se llame al ctor, en cuyo caso procederá como de costumbre. Si este parámetro es falso, significa que otra instancia ya tiene propiedad/se está ejecutando, en cuyo caso mostrará un mensaje de error "Ya se está ejecutando otra instancia". y luego salir con gracia

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()); 
    } 
} 

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

+1

Este código no es seguro ni correcto ... http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567 –

+1

' Global 'lo hace global para la máquina, no el usuario en ejecución. Por lo tanto, en un entorno de servidor o servicios de terminal, solo un usuario podría ejecutarlo a la vez. Creo que la mayoría de los usuarios esperan que una sola instancia signifique una sola instancia para ellos. –

1

Yo uso este:

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

Uso de aplicaciones con la configuración de tiempo de espera y de seguridad. Yo uso mi clase personalizada:

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(); 
      } 
     } 
    } 

y lo uso:

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"); 
     } 
    } 
Cuestiones relacionadas