Ensuring that only a single instance of a .NET application is running

Michael A. Covington
Institute for Artificial Intelligence
The University of Georgia
Athens, Georgia


Last revised 2004 February 20

Introduction

Often, to keep users from getting confused, or to keep from trashing files, you'll want to block the user from launching more than one instance of a program at a time. There are many ways to do this. Here I briefly discuss one that has been widely publicized with a subtle mistake in it, and another that is slower but more versatile.

The examples are in C# but are easily translatable to Visual Basic and J#.


The mutex method

A "mutex" (short for "mutual exclusion") is an operating-system object that can be used to keep processes from interfering with each other.

Basically, the process that doesn't want to be interfered with will create a mutex, which the operating system will keep track of. Other processes will try to obtain the same mutex and will be blocked from executing if they do not do so. See any book on threading to learn more about this.

A popular and quick way to ensure that only one instance of your program is running is to have it create a mutex with a specific name, or bail out if it cannot do so (because another copy of it is already running and owns the mutex).

Here is some correct code to do this. It's a modification to the Main method that is automatically generated.


[STAThread] static void Main() // args are OK here, of course { bool ok; m = new System.Threading.Mutex(true, "YourNameHere", out ok); if (! ok) { MessageBox.Show("Another instance is already running."); return; } Application.Run(new Form1()); // or whatever was there GC.KeepAlive(m); // important! }
Here m is, in effect, a pointer to the mutex, and its constructor takes 3 arguments: true to say "I want to own this mutex," a name (which should be unique) to identify the mutex, and a Boolean output variable that indicates whether the mutex was successfully created.

There are several ways to get this almost right. After some struggling, here's what I discovered:

I am grateful to Jon Skeet for helping me figure out why GC.KeepAlive is needed. We want the program to keep hold of the mutex as long as it's running. But the JIT compiler sees that the mutex is only used near the beginning of the program, and may discard it prematurely when memory is needed for something else! This only happens with rather large, complex programs and was a real puzzle to me. GC.KeepAlive(x) means "I'm still using x at this point so it had better not have been discarded."

An alternative is to put the mutex in a global static variable rather than a local dynamic one. But the GC.KeepAlive(x) solution is preferable, because it tells the compiler and runtime system exactly what you want.

This particular problem can be very elusive, because if you're running your program under the IDE, or if your optimization options are slightly different, the problem may never appear.


Searching the process table

Another, slower, way to ensure that you have only one instance running is to search the process table for processes that were launched from the same .exe file. This takes appreciably more time (as much as 1 second) but gives you a handle to the pre-existing process, if found, so that you can communicate with it. (How to do that is well beyond the scope of this article.) Here's a code sample:

using System.Diagnostics; public static Process PriorProcess() // Returns a System.Diagnostics.Process pointing to // a pre-existing process with the same name as the // current one, if any; or null if the current process // is unique. { Process curr = Process.GetCurrentProcess(); Process[] procs = Process.GetProcessesByName(curr.ProcessName); foreach (Process p in procs) { if ((p.Id != curr.Id) && (p.MainModule.FileName == curr.MainModule.FileName)) return p; } return null; } . . . [STAThread] static void Main() // args are OK here, of course { if (PriorProcess() != null) { MessageBox("Another instance is already running."); return; } Application.Run(new Form1()); // or whatever was here }


For more information

Some other discussions of this issue are found at:

Jon Skeet's C# FAQ (useful stuff!)

C# Programmer's Cookbook (a great book, but in Recipe 4.12, it didn't protect the mutex from GC; that's what got me into all this!)

Michael Potter's method using mutexes (elaborate)

Thom Robbins' weblog entry (process table method)

George Shepherd's Windows Forms FAQ entry (process table method)




The content and opinions expressed on this Web page do not necessarily reflect the views of,
nor are they endorsed by, the University of Georgia or the University System of Georgia.