There are several implementations out there already for doing this, but for one reason or another they all did something I didn't like. Some use the registry, some can't pass parameters, some use P/Invoke, some use remoting and others use the VB libraries. Not quite high treason but even so, an all C# and very light implementation has got to be worth the effort.
The class that does all the work is, imaginatively, called SingleInstance. The single public constructor takes a Guid which is used to identify out application. Like some of the other examples out there I use a Mutex object to tell whether the application is already running or not.
mutex = new Mutex(true, identifier.ToString(), out ownsMutex);
The out parameter tells us whether we were able to create and own the Mutex or whether someone else (another instance of our app) already has. Given this, we have a simple property telling us if we're the first instance or not.
public Boolean IsFirstInstance
{ get { return ownsMutex; } }
The only piece left of the single instance puzzle is making sure that we release the mutex, if we happen to own it, and for this I implemented IDisposable and did the following in the dispose method:
if (mutex != null && ownsMutex)
{
mutex.ReleaseMutex();
mutex = null;
}
Couldn't be more simple, right? Next we need to handle passing any command line arguments onto the initial instance. For this I use the new NamedPipeClientStream and NamedPipeServerStream classes here is the client end:
using (NamedPipeClientStream client = new NamedPipeClientStream(identifier.ToString()))
using (StreamWriter writer = new StreamWriter(client))
{
client.Connect(200);
foreach (String argument in arguments)
writer.WriteLine(argument);
}
On the server end it's pretty much just as simple, we read in all the arguments and the fire the ArgumentsReceived event which the class exposes.
using (NamedPipeServerStream server = new NamedPipeServerStream(identifier.ToString()))
using (StreamReader reader = new StreamReader(server))
{
server.WaitForConnection();
List<String> arguments = new List<String>();
while (server.IsConnected)
arguments.Add(reader.ReadLine());
ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments.ToArray());
}
Everything works really nicely, the only odd looking bit here is that we spawn a new thread to fire the event. I did this simply because I we need to create a new NamedPipeServerStream to handle any subsequent clients and I didn't want to wait for the app to have to process the event. That's all, we leave the responsibility of giving focus to the first instance to itself, should it so wish. Here is a snippet of how it looks in action.
static void Main(String[] args)
{
Guid guid = new Guid("{6EAE2E61-E7EE-42bf-8EBE-BAB890C5410F}");
using (SingleInstance singleInstance = new SingleInstance(guid))
{
if (singleInstance.IsFirstInstance)
{
singleInstance.ArgumentsReceived += singleInstance_ArgumentsReceived;
singleInstance.ListenForArgumentsFromSuccessiveInstances();
//Do whatever your application is supposed to do here...
}
else
singleInstance.PassArgumentsToFirstInstance(args);
}
}
static void singleInstance_ArgumentsReceived(object sender, ArgumentsReceivedEventArgs e)
{
//Process the arguments here...
}
One thing to note, remember to make your own Guid to use, and make a new one for each application which uses this class (Tools->Create Guid->Registry Format->Copy)! Hope you like the excessively long method names, but hey, for a code sample on a blog it makes it much clearer...
Packaged with the code download is a simple Windows Forms application to demonstrate the functionality, the best way to see it work is to launch one instance in the debugger then minimise it. Next, drag and drop some jpeg files in explorer onto the exe.

And you should see the image viewer app jump to the front and open all the images you dragged!

I'm pleased with the class, hope it can help out some others. Enjoy.
SingleInstance.zip (18.77 kb)