Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting if another instance of the application is already running

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).

like image 358
Andy Avatar asked Jul 06 '10 21:07

Andy


2 Answers

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;
like image 174
Sandor Drieënhuizen Avatar answered Oct 09 '22 11:10

Sandor Drieënhuizen


Another approach is to detect the running instance as detailed in Scott Hanselman's blog

His example activates the first instance when the second tries.

However, it wouldn't be hard to get the second instance to just stop if that's what you wanted.

like image 23
ChrisF Avatar answered Oct 09 '22 12:10

ChrisF