Share via


Create a single instance desktop application

Requirement

Sometimes a classic desktop application should only be started one time. So when the user tries to start the application a second time, the start should be interrupted and the first started application should be shown instead.

Solution

To make sure, that an application cannot be started multiple times, , a mutex could be used. A mutex can only be hold one time by any application so the first instance will grab the mutex. When the application is started a second time, getting the mutex will not be successful so we know that the application is already running.

To set the foreground window, the function setForegroundWindow inside the user32.dll could be used through platform invoke. To get the main window we simply look up the Process with the same name as our current process.

Implementation

Windows Forms

The implementation for Windows Forms is straight forward because the Main routine will not end till the application ends. So we could create the mutex inside a using statement which will make sure that the mutex is released at the end.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
 
namespace FormsApp
{
    static class  Program
    {
        /// <summary>
        /// Name of mutex to use. Should be unique for all applications.
        /// </summary>
        public const  string MutexName = "FormsApplicationMutex";
 
        /// <summary>
        /// Sets the foreground window.
        /// </summary>
        /// <param name="hWnd">Window handle to bring to front.</param>
        /// <returns></returns>
        [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()
        {
            // Try to grab mutex
            bool createdNew;
            using (var mutex = new Mutex(true, MutexName, out  createdNew))
            {
                if (createdNew)
                {
                    // We got the mutex and start the application
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    // Bring other instance to front and exit.
                    Process current = Process.GetCurrentProcess();
                    foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                    {
                        if (process.Id != current.Id)
                        {
                            SetForegroundWindow(process.MainWindowHandle);
                            break;
                        }
                    }
                }
            }
        }
    }
}

Windows Presentation Foundation (WPF)

Inside a Windows Presentation Foundation application we do not have a Main routine that we could change. But we have our Application class where we can add a constructor and store the mutex inside an instance variable.

To release the mutex at the end, we can subscribe to the Exit event of the WPF Application.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
 
namespace WpfApp
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial  class App : Application
    {
        /// <summary>
        /// Mutex used to allow only one instance.
        /// </summary>
        private Mutex _mutex;
 
        /// <summary>
        /// Name of mutex to use. Should be unique for all applications.
        /// </summary>
        public const  string MutexName = "WpfApplicationMutex";
 
        /// <summary>
        /// Sets the foreground window.
        /// </summary>
        /// <param name="hWnd">Window handle to bring to front.</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern  bool SetForegroundWindow(IntPtr hWnd);
 
        /// <summary>
        /// Creates a new instance of <see cref="App"/>.
        /// </summary>
        public App()
        {
            // Try to grab mutex
            bool createdNew;
            _mutex = new  Mutex(true, MutexName, out  createdNew);
 
            if (!createdNew)
            {
                // Bring other instance to front and exit.
                Process current = Process.GetCurrentProcess();
                foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                {
                    if (process.Id != current.Id)
                    {
                        SetForegroundWindow(process.MainWindowHandle);
                        break;
                    }
                }
                Application.Current.Shutdown();
            }
            else
            {
                // Add Event handler to exit event.
                Exit += CloseMutexHandler;
            }
        }
 
        /// <summary>
        /// Handler that closes the mutex.
        /// </summary>
        /// <param name="sender">Sender of the event.</param>
        /// <param name="e">Event arguments.</param>
        protected virtual  void CloseMutexHandler(object sender, EventArgs e)
        {
            _mutex?.Close();
        }
    }
}

References