En .NET, ¿cuál es la mejor manera de evitar que se ejecuten varias instancias de una aplicación al mismo tiempo? Y si no hay una "mejor" técnica, ¿cuáles son algunas de las advertencias a considerar con cada solución?¿Prevenir múltiples instancias de una aplicación determinada en .NET?
Respuesta
Usar Mutex. Uno de los ejemplos anteriores que usan GetProcessByName tiene muchas salvedades. Aquí es un buen artículo sobre el tema:
http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
[STAThread]
static void Main()
{
using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
Application.Run(new Form1());
}
}
private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0-Single-Instance_Detection_and_Management
En este artículo se explica simplemente cómo se puede crear una aplicación de Windows con el control del número de sus instancias o ejecutar sólo sola instancia. Esta es una necesidad muy típica de una aplicación comercial. Ya hay muchas otras soluciones posibles para controlar esto.
http://www.openwinforms.com/single_instance_application.html
Hanselman tiene a post sobre el uso de la clase WinFormsApplicationBase del conjunto Microsoft.VisualBasic para hacer esto.
He estado usando que un par de años, pero ahora estoy buscando para cambiar a una solución basada en la exclusión mutua. Tengo clientes que informan problemas con esto y sospecho que está usando Remoting para hacerlo. –
usted tiene que utilizar System.Diagnostics.Process.
Normalmente se hace con un objeto mutex llamado (uso de las nuevas mutex ("el nombre de la aplicación", true) y compruebe el valor de retorno), pero también hay algunas clases de apoyo en Microsoft.VisualBasic. dll que can do it for you.
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
AppLog.Write("Application XXXX already running. Only one instance of this application is allowed", AppLog.LogMessageType.Warn);
return;
}
Creo que debería ver esto: http: //odetocode.com/blogs/scott/archive/2004/08/20/the-misunderstood-mutex.aspx – SubmarineX
@SubmarineX ¿Cómo está seguro de que este artículo es correcto? todavía es controversia entre mutex y http://www.codeproject.com/Articles/4975/Fly-Create-A-Single-Instance-Application –
Increíble Simplemente perfecto gracias por su tiempo y esfuerzos –
mediante Visual Studio 2005 o 2008, cuando se crea un proyecto para un ejecutable, en las ventanas de propiedades dentro del panel "Aplicación" hay una casilla de verificación denominada “Hacer aplicación de instancia única” que puede activar para convertir la aplicación en una aplicación de instancia única.
Aquí hay una captura de la ventana de la que estoy hablando: Este es un proyecto de aplicación de Windows Visual Studio 2008.
Busqué esta casilla de verificación que mencionas para mi aplicación C#/WPF, y no hay ninguna. – HappyNomad
No lo veo en mis propiedades de la aplicación VS 2008 C#/WinForms tampoco. –
No en VS2005 también. Debe mencionar el viejo estudio de VB. – nawfal
Parece que hay 3 técnicas fundamentales que se han propuesto hasta ahora.
- derivados de la clase Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase y establezca la propiedad IsSingleInstance true. (Creo que una advertencia aquí es que esto no funcionará con las aplicaciones de WPF, ¿o sí?)
- Use un mutex con nombre y compruebe si ya se ha creado.
- Obtenga una lista de procesos en ejecución y compare los nombres de los procesos. (Esto tiene la salvedad de requerir que el nombre de su proceso sea único en relación con cualquier otro proceso que se ejecute en la máquina de un usuario determinado.)
¿Alguna advertencia que me he perdido?
No creo que 3 sea muy eficiente. Yo votaría por el Mutex, lo usé sin problemas muchas veces. Nunca he usado el elemento 1, no estoy seguro de cómo vuela cuando estás en C#. – typemismatch
La opción 1 aún funciona con WPF; es algo más complicada. http://msdn.microsoft.com/en-us/library/ms771662.aspx –
¿Cómo funciona 2 con usuarios de multilínea en un servidor de terminal? – SillyMonkey
Aquí está el código que necesita para asegurarse de que solo se está ejecutando una instancia. Este es el método de usar un mutex con nombre.
public class Program
{
static System.Threading.Mutex singleton = new Mutex(true, "My App Name");
static void Main(string[] args)
{
if (!singleton.WaitOne(TimeSpan.Zero, true))
{
//there is already another instance running!
Application.Exit();
}
}
}
¡Utilice VB.NET! No: realmente;)
utilizando Microsoft.VisualBasic.ApplicationServices;
WindowsFormsApplicationBase de VB.Net le proporciona una propiedad "SingleInstace", que determina otras instancias y permite que solo se ejecute una instancia.
[STAThread]
static void Main() // args are OK here, of course
{
bool ok;
m = new System.Threading.Mutex(true, "YourNameHere", out ok);
if (! ok)
{
MessageBox.Show("Another instance is already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
GC.KeepAlive(m); // important!
}
Desde: Ensuring a single instance of .NET Application
y: Single Instance Application Mutex
La misma respuesta que @Smink y @Imjustpondering con una peculiaridad:
Jon Skeet's FAQ on C# para averiguar por qué GC.KeepAlive importa
-1, porque no puede usar un bloque de uso con el mutex, lo que haría que KeepAlive sea superfluo. Y sí, creo que John Skeet lo malinterpretó. No explica por qué sería incorrecto deshacerse del mutex en este caso. –
Este es el código para VB.Net
Private Shared Sub Main()
Using mutex As New Mutex(False, appGuid)
If Not mutex.WaitOne(0, False) Then
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Application.Run(New Form1())
End Using
End Sub
Este es el código para C#
private static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid)) {
if (!mutex.WaitOne(0, false)) {
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Application.Run(new Form1());
}
}
(Nota: esta es una solución de diversión! Funciona pero usa un diseño malo GDI + para lograr esto.)
Pon una imagen con tu aplicación y cárgala al iniciar. Sosténgalo hasta que la aplicación salga. El usuario no podrá iniciar una segunda instancia. (Por supuesto, la solución es mucho más limpio mutex)
private static Bitmap randomName = new Bitmap("my_image.jpg");
he intentado todas las soluciones aquí y nada funcionó en mi proyecto de C# .NET 4.0. Con la esperanza de ayudar a alguien aquí la solución que funcionó para mí:
Como principales variables de clase:
private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;
Cuando es necesario comprobar si la aplicación ya está en ejecución:
bool mutexCreated;
mutex = new Mutex(true, "Global\\" + appGuid, out mutexCreated);
if (mutexCreated)
mutex.ReleaseMutex();
if (!mutexCreated)
{
//App is already running, close this!
Environment.Exit(0); //i used this because its a console app
}
que necesitaba para cerrar otras istancias solo con algunas condiciones, esto funcionó bien para mi propósito
Bien, tuviste éxito. Gracias hombre. –
No necesita adquirir realmente el mutex y liberarlo. Todo lo que necesita saber es si otra aplicación ya creó el objeto (es decir, su recuento de referencia del kernel> = 1). –
Esto funcionó para mí en C# puro. el try/catch es cuando posiblemente un proceso en la lista sale durante su ciclo.
using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
int procCount = 0;
foreach (Process pp in Process.GetProcesses())
{
try
{
if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
{
procCount++;
if(procCount > 1) {
Application.Exit();
return;
}
}
}
catch { }
}
Application.Run(new Form1());
}
Después de probar múltiples soluciones, la pregunta. Terminé usando el ejemplo de WPF aquí: http://www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one-instance/
public partial class App : Application
{
private static Mutex _mutex = null;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "MyAppName";
bool createdNew;
_mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
//app is already running! Exiting the application
Application.Current.Shutdown();
}
}
}
En App.xaml:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
1 - Crear una referencia en el programa.CS ->
using System.Diagnostics;
2 - Poner en void Main()
como la primera línea de código ->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
Eso es todo.
¿Cuál es la diferencia de esto a 'Mutex'? Hay una trampa? –
Simplemente usando un StreamWriter
, ¿qué tal esto?
System.IO.File.StreamWriter OpenFlag = null; //globally
y
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
Asegúrese de considerar la seguridad al restringir una aplicación a una sola instancia:
Artículo completo: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
Estamos utilizando un mutex llamado con un nombre fijo para detectar si otra copia o f el programa se está ejecutando. Pero eso también significa que un atacante puede crear el mutex primero, impidiendo así que nuestro programa se ejecute. ¿Cómo puedo evitar este tipo de denegación de servicio ataque?
...
Si el atacante está en ejecución en el mismo contexto de seguridad como el programa de es (o sería) que se ejecuta en, entonces no hay nada que puedas hacer. Sea cual sea el "saludo secreto" que se le ocurra para determinar si se está ejecutando otra copia de su programa , el atacante puede imitarlo. Dado que se ejecuta en el contexto de seguridad correcto, puede hacer cualquier cosa que el programa "real" pueda hacer.
...
Es evidente que no puede protegerse de un atacante ejecutar en el mismo privilegio de seguridad, pero todavía se puede protegerse contra atacantes no privilegiados funcionando a otros privilegios de seguridad.
Pruebe a establecer una DACL en el mutex, aquí es la forma en .NET: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx
- 1. Aplicación ASP.NET instalador de MSI instancias múltiples
- 2. Múltiples instancias de una sola DLL MEF
- 3. Múltiples instancias en una página con Javascript
- 4. Múltiples instancias de Redis
- 5. Aislamiento en una aplicación ASP .NET de múltiples usuarios
- 6. ¿Cómo prevenir CSRF en una aplicación RESTful?
- 7. ¿Múltiples instancias de iPhone Simulator?
- 8. Impedir la apertura de múltiples instancias de la aplicación VB
- 9. Múltiples instancias de variables estáticas
- 10. Javascript str.search() instancias múltiples
- 11. ¿Cómo prevenir múltiples definiciones en C?
- 12. Borrar cookies para una aplicación iOS determinada
- 13. Impedir instancias de formularios múltiples
- 14. Múltiples instancias de autocompletar de jQuery en una página
- 15. ¿Cómo prevenir múltiples publicaciones en MVC3?
- 16. Múltiples instancias de intención pendiente
- 17. Restringir varias instancias de una aplicación
- 18. Múltiples instancias de Google Maps en una página
- 19. ¿Por qué varias instancias de una aplicación django?
- 20. Múltiples instancias de IntentService en Android
- 21. Prevenir eventos de clics múltiples activando JQuery
- 22. Nombrar contadores de rendimiento de varias instancias en .NET
- 23. Iniciando múltiples instancias upstart automáticamente
- 24. Prevenir .NET de "lifting" variables locales
- 25. ¿Cómo puedo iniciar varias instancias de una aplicación usando launchd?
- 26. ¿Cuál de las siguientes expresiones Mutex previene idealmente múltiples instancias de la aplicación .Net y cuál es la diferencia?
- 27. Prevención de múltiples instancias de proceso en Linux
- 28. Prevenir selecciones múltiples del mismo valor
- 29. apio con múltiples instancias de django
- 30. ¿Está asociada una aplicación con una extensión determinada?
El uso de un mutex también funciona para el código nonnet también (aunque la sintaxis podría variar) – crashmstr
Este código debe manejar agandonedmutexexceptions –
Aquí hay una versión un poco más completa, con algunos buenos comentarios: http://stackoverflow.com/ questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567 –