Detecting if another instance of the application is already running

Andy picture Andy · Jul 6, 2010 · Viewed 12.2k times · Source

My application needs to behave slightly differently when it loads if there is already an instance running.

I understand how to use a mutex to prevent additional instances loading, but that doesn't quite solve my problem.

For example:

  • Instance 1 loads, gets the mutex.
  • Instance 2 loads, can't get the mutex, knows there's another instance. So far, so good.
  • Instance 1 closes, releases the mutex.
  • Instance 3 loads, gets the mutex, doesn't know that Instance 2 is still running.

Any ideas? Thankfully it doesn't need to deal with multiple user accounts or anything like that.

(C#, desktop application)

Edit: To clarify, the application doesn't need to be restricted to a single instance, just perform a slightly different start-up action if there's another instance already running. Multiple instances are fine (and expected).

Answer

Sandor Drieënhuizen picture Sandor Drieënhuizen · Jul 6, 2010

This will probably do just what you want. It has the nice additional feature of bringing the already running instance forward.

EDIT: updated the code to determine the application title automatically.

using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;

static void Main()
{
    if (!EnsureSingleInstance())
    {
        return;
    }

    //...
}

static bool EnsureSingleInstance()
{
    Process currentProcess = Process.GetCurrentProcess();

    var runningProcess = (from process in Process.GetProcesses()
                          where
                            process.Id != currentProcess.Id &&
                            process.ProcessName.Equals(
                              currentProcess.ProcessName,
                              StringComparison.Ordinal)
                          select process).FirstOrDefault();

    if (runningProcess != null)
    {
        ShowWindow(runningProcess.MainWindowHandle, SW_SHOWMAXIMIZED);
        SetForegroundWindow(runningProcess.MainWindowHandle);

        return false;
    }

    return true;
}

[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

private const int SW_SHOWMAXIMIZED = 3;