This article shows yet another technique on how to include support for activating an already running instance of your application when a user tries to start a new instance.
The differences between this technique and others I've found on The Code Project are:
- Support for scenarios where you sometimes want to start a new instance even if an existing instance is already running
- Send data to the existing application when a new instance tries to start
To understand the implementation, the article discusses the following subjects:
- Using a mutex to determine if the application is already running
- Using .NET
NativeWindow class to implement a Windows message loop without requiring a Form
- Sending messages between applications using
The class described here is used in an open source project called Terminals that me and a friend are working on. The project is a multi-tabbed RDP client that can be found here.
The Terminals application allows you to pass a server name on the command line so it can connect to it as soon as the application starts (i.e. Terminals.exe Server1). One of our users requested that if a new instance is started with a command line (i.e. Terminals.exe server2) that the new connection will be opened in a new tab instead of starting a new process. We also wanted to still support a scenario where a user starts a new instance.
Note: This works exactly the way Internet Explorer 7 does. If you enter the URL of a site in the Start->Run command, it will open in a new tab if Internet Explorer is already running, but you can still start new instances if you start Internet Explorer directly from its shortcut.
Using the Code
The class is implemented as a singleton with
static methods for ease of use. Start by calling
SingleInstanceApplication.NotifyExistingInstance(). This will check if another instance already exists and if so, it will send it the data passed to the function. The data can be any .NET object that is serializable.
if (SingleInstanceApplication.NotifyExistingInstance("Some data"))
Next, if another instance does not already exist, you should call the
If you want to get notifications when a new instance is started, subscribe to the
SingleInstanceApplication.NewInstanceMessage += new NewInstanceMessageEventHandler(
void SingleInstanceApplication_NewInstanceMessage(object sender,
Ok, let's dive into the implementation details, taking one step at a time.
Determining If Another Instance is Already Running
The easiest way to determine if another instance is already running is simply to create a
Mutex object when the application starts. The nice thing about
Mutexes is that when you create them, you can:
- Give them a name so they will be accessible from more than 1 process.
- Provide an
out parameter to their constructor that will be
true if this is the first instance if the
So basically, we do this:
_instanceCounter = new Mutex(false, _id, out _firstInstance);
_Id is the name of the
Mutex which is actually the name of the application EXE.
_firstInstance will be set to
true if this is the first instance of the
Mutex. Notice that the first parameter to the
Mutex constructor determines whether to lock the
mutex. We don't want to lock it - we only care whether it already exists or not.
Notifying the Existing Instance that Another Instance was Started
Great. So now whenever a new instance starts, it checks the
_firstInstance variable and knows if another instance was already started. If so, we need to notify the other instance and possibly provide it with some information. (In the case of the Terminals project mentioned above, we needed to pass the command line parameters we received).
So how do we notify the other window? I've seen some solutions using Remoting, some using shared memory and some ignoring the problem altogether. I decided to use the simplest Windows mechanism to communicate between processes: Windows Messages.
The idea is to create our own hidden window that will have a title with a unique id that we can identify and send a message to that window. How do you create a hidden window in .NET without creating a Form? Simple: Use the
What you need to do is create a subclass of
NativeWindow and override its
class SIANativeWindow : NativeWindow
CreateParams cp = new CreateParams();
cp.Caption = _theInstance._id; CreateHandle(cp);
protected override void WndProc(ref Message m)
So, we have a hidden window that can accept messages. Which message should we send it? Since we need to pass data and not the usual
Long parameters that are usually passed with messages, the perfect fit is WM_COPYDATA. This message was created exactly for that purpose - to pass data between applications.
Sending Data between Applications using WM_COPYDATA
Let's get to work then. The first thing we need to do is find our hidden window:
IntPtr handle = NativeMethods.FindWindow(null, _id);
We serialize the object we want to send to a byte array and now we need to fill the
WM_COPYDATA structures with the correct information. Since we are using native Windows APIs to send the message and since our byte array is a .NET object, we first need to Pin our object in memory and get a "native" pointer to it:
bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
data.lpData = bufferHandle.AddrOfPinnedObject();
And now we just need to send the data to our window:
(handle, NativeMethods.WM_COPYDATA, IntPtr.Zero, dataHandle.AddrOfPinnedObject());
Handling the WM_COPYDATA on the Other End of the Pipe
Ok now - The application was found, the window was found, the message was sent. The last thing we have to do is actually handle that message in the hidden window we created above.
Again, since the message arrives as a native
WM_COPYDATA structure, we first have to convert it to a .NET byte array and then deserialize the original object.
COPYDATASTRUCT data = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam,
byte buffer = new byte[data.cbData];
Marshal.Copy(data.lpData, buffer, 0, buffer.Length);
obj = Deserialize(buffer);
We now have a copy of the object that was sent from the new application instance. We can activate our window, do something with the information passed to us (e.g. create a new tab and connect to another server as in the Terminals application).
This class allows you create a "Singleton" application and pass information between new instances of the application and existing instances. It uses very simple mechanisms to determine if the application is already running (
Mutex) and to communicate between applications (Windows messages).
- 14th March, 2007: Initial post