2008-10-08 64 views

Respuesta

95

Prefiero una solución mutex similar a la siguiente. Como esta manera se re-centra en la aplicación si ya está cargado

using System.Threading; 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SetForegroundWindow(IntPtr hWnd); 

/// <summary> 
/// The main entry point for the application. 
/// </summary> 
[STAThread] 
static void Main() 
{ 
    bool createdNew = true; 
    using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew)) 
    { 
     if (createdNew) 
     { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new MainForm()); 
     } 
     else 
     { 
     Process current = Process.GetCurrentProcess(); 
     foreach (Process process in Process.GetProcessesByName(current.ProcessName)) 
     { 
      if (process.Id != current.Id) 
      { 
       SetForegroundWindow(process.MainWindowHandle); 
       break; 
      } 
     } 
     } 
    } 
} 
+6

Solo un poco de información sobre el uso de la propiedad MainWindowHandle de esta forma (como acabo de descubrir): "Si el proceso asociado no tiene una ventana principal, * el valor de MainWindowHandle es cero *. El valor es * también cero * para procesos que se han ocultado, es decir, procesos que no son visibles en la barra de tareas. Este puede ser el caso de los procesos que aparecen como iconos en el área de notificación, en el extremo derecho de la barra de tareas ". –

+0

Buena respuesta. Me gusta el uso de SetForegroundWindow sobre la respuesta de aceptación (si sigues ese enlace más el siguiente enlace) que utiliza un mensaje de difusión y obliga a la ventana a la parte superior, que en realidad no enfocará la ventana. Esta respuesta debería, porque el proceso recién ejecutado tiene derecho a pasar el foco a otro proceso en la mayoría de los casos. – eselk

+3

SetForegroundWindow no funciona para mí. Nunca funcionó, en realidad. –

9

Esto es lo que yo uso en mi solicitud:

static void Main() 
{ 
    bool mutexCreated = false; 
    System.Threading.Mutex mutex = new System.Threading.Mutex(true, @"Local\slimCODE.slimKEYS.exe", out mutexCreated); 

    if(!mutexCreated) 
    { 
    if(MessageBox.Show(
     "slimKEYS is already running. Hotkeys cannot be shared between different instances. Are you sure you wish to run this second instance?", 
     "slimKEYS already running", 
     MessageBoxButtons.YesNo, 
     MessageBoxIcon.Question) != DialogResult.Yes) 
    { 
     mutex.Close(); 
     return; 
    } 
    } 

    // The usual stuff with Application.Run() 

    mutex.Close(); 
} 
22

para obligar a correr sólo una instace de un programa en .NET (C#) utiliza este código en Program.cs archivo:

public static Process PriorProcess() 
    // Returns a System.Diagnostics.Process pointing to 
    // a pre-existing process with the same name as the 
    // current one, if any; or null if the current process 
    // is unique. 
    { 
     Process curr = Process.GetCurrentProcess(); 
     Process[] procs = Process.GetProcessesByName(curr.ProcessName); 
     foreach (Process p in procs) 
     { 
      if ((p.Id != curr.Id) && 
       (p.MainModule.FileName == curr.MainModule.FileName)) 
       return p; 
     } 
     return null; 
    } 

y el folowing:

[STAThread] 
    static void Main() 
    { 
     if (PriorProcess() != null) 
     { 

      MessageBox.Show("Another instance of the app is already running."); 
      return; 
     } 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form()); 
    } 
+4

Esta es una forma incorrecta. Podría ejecutar su programa en dos instancias: una iniciada como binaria, la segunda de VS. – greenoldman

+6

Ok, @greenoldman, pero desde cuándo los usuarios/clientes "depuran" sus aplicaciones y luego eligen ejecutar una segunda (binaria) junto a ella. Esta respuesta es bastante buena en comparación con muchas de las etiquetas basadas en Mutex que he visto en este sitio web. –

+3

Sé que esto es años más tarde, pero en caso de que alguien encuentre esto como lo hice: Si el usuario no es un administrador (al menos en Win7) 'Process.GetProcessesByName' lanzará una excepción. –

1

Otra forma de instancia única para una aplicación es verificar sus sumas de hash. después de jugar un poco con exclusión mutua (no funcionó como yo quiero) lo tengo trabajando de esta manera:

[DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool SetForegroundWindow(IntPtr hWnd); 

    public Main() 
    { 
     InitializeComponent(); 

     Process current = Process.GetCurrentProcess(); 
     string currentmd5 = md5hash(current.MainModule.FileName); 
     Process[] processlist = Process.GetProcesses(); 
     foreach (Process process in processlist) 
     { 
      if (process.Id != current.Id) 
      { 
       try 
       { 
        if (currentmd5 == md5hash(process.MainModule.FileName)) 
        { 
         SetForegroundWindow(process.MainWindowHandle); 
         Environment.Exit(0); 
        } 
       } 
       catch (/* your exception */) { /* your exception goes here */ } 
      } 
     } 
    } 

    private string md5hash(string file) 
    { 
     string check; 
     using (FileStream FileCheck = File.OpenRead(file)) 
     { 
      MD5 md5 = new MD5CryptoServiceProvider(); 
      byte[] md5Hash = md5.ComputeHash(FileCheck); 
      check = BitConverter.ToString(md5Hash).Replace("-", "").ToLower(); 
     } 

     return check; 
    } 

comprueba sólo las sumas MD5 de Identificación del proceso.

si se encontró una instancia de esta aplicación, enfoca la aplicación en ejecución y sale por sí misma.

puede cambiar el nombre o hacer lo que desee con su archivo. no se abrirá dos veces si el hash md5 es el mismo.

¿alguien tiene alguna sugerencia para ello? Sé que se responde, pero tal vez alguien está buscando una alternativa mutex.

Cuestiones relacionadas