2010-12-06 21 views

Respuesta

44

me gustaría utilizar un 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

Gracias SwDevMan81 de fragmento de código. –

+1

¿Puede esto restringirse a un cierto número de instancias también? –

+0

Gracias. Estoy usando esto en un proyecto de WinForms en VS2015. Combiné lo anterior con Main() en program.cs, para que la ubicación "// Do stuff" tuviera estas 3 líneas generadas por VS: "Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault (false); Application.Run (nuevo Form1()); "También se agregó" usando System.Threading; "en la parte superior de program.cs. – gus

18

Hay muchas maneras, tales como -

  • lista de enumeración de procesos antes de empezar y negar el proceso de puesta en marcha si el nombre ya existe.
  • Creando un mutex en el arranque y comprobando si el mutex ya existe.
  • Lanzando un programa a través de una clase singleton.

Cada uno se hizo una demostración a continuación:

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

Cada uno tiene sus ventajas y desventajas. Pero creo que la creación de mutex es la mejor opción.

+5

+1 para las alternativas no mutex –

31

Si decide utilizar un mutex para ese propósito, hay algunas trampas que usted debe tener en cuenta:

  • Si desea limitar la aplicación a una instancia por la máquina (es decir, no uno por cada conectado en usuario), entonces necesitará su nombre mutex para comenzar con el prefijo Global\. Si no agrega este prefijo, el SO creará una instancia diferente del mutex para cada usuario.

  • Si está ejecutando en una máquina Win7/Vista con UAC habilitado y, por casualidad, la instancia actual de la aplicación se ejecuta como administrador, las próximas instancias no lo detectarán y obtendrá excepciones de permisos. Para evitar esto, debe especificar un conjunto diferente de permisos para el Mutex al crearlo.

+6

Buenas trampas. Otra es que si está ejecutando dos programas que se odian, uno de ellos podría intentar montar un ataque de denegación de servicio contra el usuario sacando el mutex nombrado del otro programa y nunca soltándolo. –

+3

Bueno ... Pero dudo que valga la pena protegerlo, ya que un programa "malo", una vez que confías lo suficiente como para ejecutarlo, puede estropear otros programas de todos modos y no necesita el mutex para eso. Por ejemplo, puede matar a otros procesos, dañar los archivos instalados del otro programa, cambiar sus accesos directos o desinstalarlo por completo ... – Ran

+0

@Ran: Claro, esto es de alguna manera uno de los "ya está detrás de la escotilla hermética" de Raymond Chen " cuestiones. Sin embargo, el nivel de permisos necesarios para eliminar un mutex puede ser diferente del nivel de permiso necesario para hacer esas otras cosas, que todos deben requerir plena confianza. No sé si los programas parcialmente confiables pueden sacar los mutexes con nombre o no; sería interesante averiguarlo. –

2

aquí es una solución que funcionó para mí

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

I a continuación, comprobar la salida de este método al inicio del programa.

+0

En núcleo .net (al menos Linux) parece que vale la pena comprobar si process.Modules.Count> 0. Es mejor prevenir las excepciones que dejarlas pasar e ignorar ¿no? – Theyouthis

2

Agregando esta respuesta porque las anteriores no funcionaron en Linux (se probó Ubuntu 14.0.4) con .net core1.1 y porque esta pregunta está muy arriba en los resultados de búsqueda. Variación de la solución de @ MusuNaji, si no era ya obvio para ti.

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

Esta respuesta también se publica en mi pregunta específica núcleo dotnet aquí: Single instance dotnetcore cli app on linux

0

La respuesta más directo para mí, se muestra a continuación, tomado de Madhur Ahuja publicada enlace (http://www.webskaper.no/wst/creatingasingleinstanceapplicationinc-aspx/) - reproduce aquí (las soluciones del proyecto de código estaban ocultas para mí).

El punto importante era mantener el mutex hasta que el proceso esté completo (obviamente, supongo).

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