Pregunta

Tengo una aplicación de Windows (C #) y tengo que configurarlo para ejecutar una instancia de la aplicación en el momento, significa que un usuario hace clic en el archivo .exe y se ejecuta la aplicación y el usuario no se cerró la primera instancia de la aplicación que se está ejecutando y la necesidad de ejecutar una siguiente instancia por lo que debería aparecer el primer caso y no abrir uno nuevo.

Puede alguien ayudarme cómo hacerlo?

Gracias de antemano

¿Fue útil?

Solución

A menudo solucionar esto mediante la comprobación de otros procesos con el mismo nombre. La ventaja / desventaja de esto es que usted (o el usuario) puede "hacerse a un lado" de la comprobación cambiando el nombre del exe. Si no desea que probablemente podría utilizar el Proceso-objeto que se devuelve.

  string procName = Process.GetCurrentProcess().ProcessName;
  if (Process.GetProcessesByName(procName).Length == 1)
  {
      ...code here...
  }

Depende de su necesidad, creo que es útil para omitir la comprobación de witout recompilar (que es un proceso de servidor, que a veces se ejecuta como un servicio).

Otros consejos

El equipo VB.Net ya ha implementado una solución. Tendrá que tomar una dependencia de Microsoft.VisualBasic.dll, pero si eso no te molesta, entonces esta es una buena solución en mi humilde opinión. Consulte el final del siguiente artículo: Single-Instancia Aplicaciones

He aquí las partes pertinentes del artículo:

1) Añadir una referencia a Microsoft.VisualBasic.dll 2) Añada la siguiente clase a su proyecto.

public class SingleInstanceApplication : WindowsFormsApplicationBase
{
    private SingleInstanceApplication()
    {
        base.IsSingleInstance = true;
    }

    public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
    {
        SingleInstanceApplication app = new SingleInstanceApplication();
        app.MainForm = f;
        app.StartupNextInstance += startupHandler;
        app.Run(Environment.GetCommandLineArgs());
    }
}

Abrir Program.cs y agregue la siguiente instrucción using:

using Microsoft.VisualBasic.ApplicationServices;

Cambiar la clase a lo siguiente:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SingleInstanceApplication.Run(new Form1(), StartupNextInstanceEventHandler);
    }

    public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
    {
        MessageBox.Show("New instance");
    }
}

Editar: Después de la pregunta se modificó para incluir C #. Mi respuesta sólo funciona para la aplicación vb.net

seleccione la casilla Hacer aplicación de instancia única verificación para evitar que los usuarios ejecuten múltiples instancias de su aplicación. El ajuste de esta casilla de verificación está desactivada por defecto, lo que permite múltiples instancias de la aplicación que se ejecute.

Puede hacerlo desde Proyecto -> Propiedades -> pestaña de aplicaciones

Fuente

Hemos tenido exactamente el mismo problema. Probamos el enfoque basado en procesos, pero esto no funciona, si el usuario no tiene derecho a leer más información sobre otros procesos, es decir, que no son administradores. Así que hemos implementado la solución a continuación.

Básicamente intenta abrir un archivo para lectura exclusiva. Si esto no funciona (porque anohter ejemplo ya lo ha hecho), obtenemos una excepción y se puede salir de la aplicación.

        bool haveLock = false;
        try
        {
            lockStream = new System.IO.FileStream(pathToTempFile,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,System.IO.FileShare.None);
            haveLock = true;
        }
        catch(Exception)
        {
            System.Console.WriteLine("Failed to acquire lock. ");
        }
        if(!haveLock)
        {
            Inka.Controls.Dialoge.InkaInfoBox diag = new Inka.Controls.Dialoge.InkaInfoBox("App has been started already");
            diag.Size = new Size(diag.Size.Width + 40, diag.Size.Height + 20);
            diag.ShowDialog();
            Application.Exit();
        }

Si se asume que está usando C #

        static Mutex mx;
        const string singleInstance = @"MU.Mutex";
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                System.Threading.Mutex.OpenExisting(singleInstance);
                MessageBox.Show("already exist instance");
                return;
            }
            catch(WaitHandleCannotBeOpenedException)
            {
                mx = new System.Threading.Mutex(true, singleInstance);

            }
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }

que haría uso de un Mutex para este escenario. Alternativamente, un Semaphore también funcionaría (pero un Mutex parece más apto).

Aquí está mi ejemplo (desde una aplicación de WPF, pero los mismos principios deben aplicarse a otros tipos de proyectos):

public partial class App : Application
{
    const string AppId = "MY APP ID FOR THE MUTEX";
    static Mutex mutex = new Mutex(false, AppId);
    static bool mutexAccessed = false;

    protected override void OnStartup(StartupEventArgs e)
    {
        try
        {
            if (mutex.WaitOne(0))
                mutexAccessed = true;
        }
        catch (AbandonedMutexException)
        {
            //handle the rare case of an abandoned mutex
            //in the case of my app this isn't a problem, and I can just continue
            mutexAccessed = true;
        }

        if (mutexAccessed)
            base.OnStartup(e);
        else
            Shutdown();
    }

    protected override void OnExit(ExitEventArgs e)
    {
        if (mutexAccessed)
            mutex?.ReleaseMutex();

        mutex?.Dispose();
        mutex = null;
        base.OnExit(e);
    }
}

, que es un trabajo!

 /// <summary>
        /// The main entry point for the application.
        /// Limit an app.to one instance
        /// </summary>
        [STAThread]
        static void Main()
        {
            //Mutex to make sure that your application isn't already running.
            Mutex mutex = new System.Threading.Mutex(false, "MyUniqueMutexName");
            try
            {
                if (mutex.WaitOne(0, false))
                {
                    // Run the application
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    MessageBox.Show("An instance of the application is already running.",
                        "An Application Is Running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Application Error 'MyUniqueMutexName'", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            finally
            {
                if (mutex != null)
                {
                    mutex.Close();
                    mutex = null;
                }
            }
        }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top