Detecting if another instance of an application is already running

Back in Alpha 1.3 of Picsie, one of the features I added was to have the windows position differently depending on if there were already Picise instances loading.  This isn’t as simple as it sounds, and I ended up prostrating myself at the feet of Stack Overflow, begging for wisdom.

Here’s what I learned.

Mutexes make for a simple and neat way of knowing if an application is running:

  • Instance 1 loads, gets the mutex.
  • Instance 2 loads, can’t get the mutex, knows there’s another instance.

So far ,so good.  But this behaviour is usually used to limit the number of running instances to one – in this case, Instance 2 would pass control to Instance 1, which handles the action – Chrome load the URL in a new tab, for example.  Picsie has different needs – there should be multiple instances running, it just needs to behave differently at startup if it isn’t the only instance.  If it is the only instance, centre the image on the screen.  Otherwise, let Windows handle the layout like normal, to avoid overlapping where possible.  But what happens now is this:

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

And so we end up with Instance 3 using the wrong behaviour at startup.

Stack Overflow to the rescue.  What I ended up with is a solution that iterates through the currently running processes and looks for one with the same name but a different ID.  If it finds one, it knows that there is an existing instance.

 

Code:

public static bool IsSoleInstance()
{
    Process currentProcess = Process.GetCurrentProcess();
    string applicationTitle = 
        [1]AssemblyTitleAttribute)Attribute.GetCustomAttribute(
        Assembly.GetExecutingAssembly(), typeof(AssemblyTitleAttribute), false.Title;
    var runningProcess = 
        (from process in Process.GetProcesses()
        where 
            process.Id != currentProcess.Id && 
            process.ProcessName.Equals(currentProcess.ProcessName, StringComparison.Ordinal)
	select process).FirstOrDefault();
    return runningProcess == null;
}

Feet

Feet
1 AssemblyTitleAttribute)Attribute.GetCustomAttribute(         Assembly.GetExecutingAssembly(), typeof(AssemblyTitleAttribute), false

Leave a Reply

Post Navigation