vez una que programa mas evitar ejecute aplicación c# .net

c# - que - ¿Cómo determinar si se está ejecutando una instancia anterior de mi aplicación?



evitar que un programa se ejecute mas de una vez (10)

El uso de un objeto kernal es la única forma correcta de implementar la protección de una sola instancia en Windows.

Esta declaración:

mutex = Mutex.OpenExisting ("SINGLEINSTANCE");

no funcionará si alguien más copia esta línea de Stackoverflow y ejecuta su programa antes de su programa, ya que ese otro individuo tomó "SINGLEINSTANCE" antes de que usted lo hiciera. Desea incluir un GUID en su nombre de exclusión mutua:

mutex = Mutex.OpenExisting ("MyApp {AD52DAF0-C3CF-4cc7-9EDD-03812F82557E}");

Esta técnica evitará que el usuario actual ejecute más de una instancia de su programa, pero no impedirá que otro usuario lo haga.

Para asegurarse de que solo una instancia de su aplicación pueda ejecutarse en la computadora local, debe hacer esto:

mutex = Mutex.OpenExisting ("Global / MyApp {AD52DAF0-C3CF-4cc7-9EDD-03812F82557E}");

Vea la ayuda para la api de CreateMutex.

Tengo una aplicación de consola en C # en la que ejecuto varias tareas de automatización arcanas. Soy consciente de que este debería ser realmente un Servicio de Windows, ya que necesita ejecutarse continuamente, pero no quiero hacerlo en este momento. (Entonces, no sugieras eso como una respuesta).

Mientras tanto, necesito un código de C # de muestra que me permita determinar si ya existe una instancia de la aplicación en ejecución.

En los viejos días de VB6.0, habría usado App.PrevInstance()

Quiero poder hacer esto en mi método principal:

static void Main() { if(!MyApp.IsAlreadyRunning()) { while(true) { RockAndRollAllNightAndPartyEveryDay(); } } }



Este artículo habla de ello: Evita que se ejecute una segunda instancia de proceso . Está en VB.net pero puedes convertirlo.

El problema al escribir una función genérica que comprueba si la aplicación actual ya se está ejecutando se debe a que la propiedad ProcessName del objeto Process parece estar limitada a 15 caracteres , por lo que los nombres de proceso más largos se truncan.
Una forma más segura de recuperar un nombre de proceso es obtener el nombre de archivo de su módulo principal y eliminar la extensión. La siguiente rutina reutilizable utiliza este enfoque:

Function AppIsAlreadyRunning() As Boolean '' get the filename of the main module Dim moduleName As String = Process.GetCurrentProcess.MainModule.ModuleName '' discard the extension to get the process name Dim procName As String = System.IO.Path.GetFileNameWithoutExtension(moduleName) '' return true if there are 2 or more processes with that name If Process.GetProcessesByName(procName).Length > 1 Then Return True End If End Function


Jeroen ya respondió esto, pero la mejor manera es usar un Mutex ... no por Proceso. Aquí hay una respuesta más completa con código.

Mutex mutex; try { mutex = Mutex.OpenExisting("SINGLEINSTANCE"); if (mutex!= null) { Console.WriteLine("Error : Only 1 instance of this application can run at a time"); Application.Exit(); } } catch (WaitHandleCannotBeOpenedException ex) { mutex = new Mutex(true, "SINGLEINSTANCE"); }

También tenga en cuenta que necesita ejecutar su aplicación en algún tipo de bloque Probar {} Finalmente {}. De lo contrario, si la aplicación falla sin liberar el Mutex, es posible que no pueda reiniciarlo más tarde.


La forma correcta de usar un mutex para este propósito:

private static Mutex mutex; static void Main() { // STEP 1: Create and/or check mutex existence in a race-free way bool created; mutex = new Mutex(false, "YourAppName-{add-your-random-chars}", out created); if (!created) { MessageBox.Show("Another instance of this application is already running"); return; } // STEP 2: Run whatever the app needs to do Application.Run(new Form1()); // No need to release the mutex because it was never acquired }

Lo anterior no funcionará para detectar si varios usuarios en la misma máquina ejecutan la aplicación con diferentes cuentas de usuario. Un caso similar es cuando un proceso puede ejecutarse tanto en el servidor de servicio como en el modo independiente. Para hacer que esto funcione, cree la exclusión mutua de la siguiente manera:

var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); var mutexsecurity = new MutexSecurity(); mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow)); mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.ChangePermissions, AccessControlType.Deny)); mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.Delete, AccessControlType.Deny)); _mutex = new Mutex(false, "Global//YourAppName-{add-your-random-chars}", out created, mutexsecurity);

Dos diferencias aquí: en primer lugar, el mutex debe crearse con derechos de seguridad que permitan a otras cuentas de usuario abrirlo / adquirirlo. En segundo lugar, el nombre debe tener el prefijo "Global" en el caso de los servicios que se ejecutan bajo el servidor de servicio (no estoy seguro de que otros usuarios se ejecuten localmente en la misma máquina).


La forma más sencilla (y confiable) de hacer esto, es usar un Mutex. Use el método WaitOne de la clase Mutex para esperar hasta que el mutex esté disponible. Una ventaja añadida, esto no requerirá ningún bucle infinito


Otra forma de hacerlo es enlazar a una dirección en la máquina local (como lo haría un oyente TCP). Solo un proceso a la vez puede vincularse a una combinación de puerto / dirección. Así que elige un puerto en el adaptador de bucle invertido y tenlo.

Esto tiene los efectos secundarios agradables de:

  • Trabajando incluso si alguien cambia el nombre del ejecutable
  • Restablecerse a sí mismo cuando la aplicación falla
  • La técnica es portátil a través de otros sistemas operativos.

En el lado negativo, puede fallar si hay otra aplicación que se enlaza a ese puerto en particular.

Como se solicitó, a continuación se muestra un código para enlazar a una dirección / puerto. Esto es arrancado de otra cosa. Está incompleto, pero los bits necesarios están aquí.

using System.Net; using System.Net.Sockets; [...] // Make up a number that''s currently unused by you, or any // well-known service. i.e. 80 for http, 22 for ssh, etc.. int portNum = 2001; // This binds to any (meaning all) adapters on this system IPAddress ipAddress = IPAddress.Any; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portNum); Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); // The next statement will throw an exception if anyone has done this Bind! listener.Bind(localEndPoint);

Mientras el oyente no sea recolectado como basura (quede fuera del alcance) o el programa no finalice: ese puerto en ese adaptador es tuyo y solo tuyo. Si algo le sucede al listener , queda disponible para que lo use otra persona. Para los fines de un bloqueo, es probable que el listener esté estático en algún lugar.


Puede buscar nombres de proceso del proceso del sistema existente. Por ejemplo, código, ver esta entrada de blog.

También puede usar un sistema denominado Mutex para ver si su proceso ya se está ejecutando.
Aquí hay un código de ejemplo. Esto tiende a ser más confiable en mi experiencia, y es un código mucho más simple y comprensible.


Puede usar Process.GetProcessesByName("MyProcessName"); en el espacio de nombres System.Diagnostics para verificar si hay una instancia de su proceso en ejecución.

EDITAR: Muy buenas observaciones en los comentarios! Esta es una forma (muy) simplista de hacerlo, y ciertamente no cubre todas las bases.


// Allow running single instance string processName = Process.GetCurrentProcess().ProcessName; Process[] instances = Process.GetProcessesByName(processName); if (instances.Length > 1) { MessageBox.Show("Application already Running", "Error 1001 - Application Running"); return; }

Salga con gracia de la aplicación con el cuadro de mensaje como se muestra arriba si la aplicación ya se está ejecutando