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
- Code Gallery: Single Instance Desktop Application
- System.Threading.Mutex class.