Run a Single Instance of a .NET Application

Sometimes you may want to run the first-only instance of an app, other times you may want the last-only instance. Here are examples of both approaches


August 18, 2003
URL:http://drdobbs.com/windows/run-a-single-instance-of-a-net-applicati/184416856

How do you ensure that only one instance of a .NET application runs on your machine? Multitasking operating systems are useful in many respects, but sometimes you want to have just one instance of your application running at a time—for example, if the application has a large resource usage or requires exclusive access to a resource. In such a situation, you’ll want to make sure that when a second instance starts, it will check to see if another instance is running and if this is the case shut itself down. In this article, I will tell you how to do this and the related situation of only allowing the most recent application instance to run.

The simplest way to ensure that only a single instance of an application runs is to use a mutex object. For example, in the following code, the form constructor creates a mutex object and then attempts to gain access to it. If WaitOne() returns true then the current thread owns the mutex, if it returns false then the mutex is owned by another thread.

using System;
using System.Windows.Forms;
using System.Threading;

class App : Form
{
   Mutex mutex;
   App()
   {
      Text = "Single Instance!";
      mutex = new Mutex(false, "SINGLE_INSTANCE_MUTEX");
      if (!mutex.WaitOne(0, false)) 
      {
         mutex.Close();
         mutex = null;
      }
   }
   protected override void Dispose(bool disposing)
   {
      if (disposing)
         mutex.ReleaseMutex();
      base.Dispose(disposing);
   }
   static void Main()
   {
      App app = new App();
      if (app.mutex != null) Application.Run(app);
      else MessageBox.Show("Instance already running");
   }
}

In this code, the Dispose() method is not strictly necessary because when the application dies, the garbage collector will dispose the mutex object, which will release it. However, I have added this just in case the disposal of the form takes a long time and another instance of the form is attempting to start.

This solution allows only the first instance of the process to run. What about the situation when you want just the last instance to run? By this I mean that if I start a new instance of the process and there is another instance already running, that first instance should stop. One situation of when this is useful is the Screen Saver tab of the Display Properties dialog. This dialog shows a small window with a preview of the screensaver; when the user clicks on the Preview button, another instance of the screensaver is started and told to run full screen. When the full screen instance stops (you move the mouse, for example) another instance of the screensaver is started to run in the small preview window. Clearly, when the full screen instance starts, the preview window instance of the screensaver should quit.

One way to do this is for each instance to access a named event kernel object. If the event object is nonsignaled, then the instance should continue to run, and if the event is signaled then the instance should quit. The application can periodically test the event to see if it has signaled. When a new instance starts, it should set the event (to close any other instances) and then reset the event so that it can continue to run. This scheme is fine except for one small problem: The .NET framework does not allow you to give a name to a kernel event. Here’s a class that will do this work for you:

public class NamedEventHelper
{
   [DllImport("kernel32")]
   static extern uint CreateEvent(
      uint sec, bool manualReset, bool initialState, string name);
   static IntPtr CreateEvent(bool manualReset, bool initialState, string name)
   {
      return new IntPtr(CreateEvent(0, manualReset, initialState, name));
   }
   [DllImport("kernel32")]
   static extern bool CloseHandle(IntPtr handle);
   public static ManualResetEvent CreateNamedEvent(
      bool initialState, string name)
   {
      ManualResetEvent mre = new ManualResetEvent(false);
      CloseHandle(mre.Handle);
      mre.Handle = CreateEvent(true, initialState, name);
      return mre;
   }
}

In this code, the static method CreateNamedEvent() creates a ManualResetEvent object and then releases the underlying Win32 handle. The method then creates a named event and initializes the ManualResetEvent object with the handle of this new event. The event object can then be used to communicate between two applications.

The weak point in this scheme is the fact that an application has to poll to see if it should die. One way to do this is to run a background thread to monitor the event:

  
ManualResetEvent mre;
mre = NamedEventHelper.CreateNamedEvent(false, "LAST_INSTANCE_ONLY");
// Stop the other instances
mre.Set();
// Reset the event so that we can run
mre.Reset();
// Create a monitor thread
Thread t = new Thread(new ThreadStart(Monitor));
// Make sure that this thread cannot keep the app alive
t.IsBackground = true;
t.Start();

The Monitor() method looks like this:

void Monitor()
{
   mre.WaitOne();
   Application.Exit();
}

If the application has a window, then another solution to this issue is for the new instance to tell the other window to close. If this was a Win32 application, then the application can simply call FindWindowEx() to get the window with a specified Windows class and then post the WM_CLOSE message. However, you cannot do this with Windows Forms because most forms will have the same class name, as I explained in the last newsletter. In the next newsletter, I will explain another way to get around this issue.


Richard Grimes speaks at conferences and writes extensively on .NET, COM, and COM+. He is the author of Developing Applications with Visual Studio .NET (Addison-Wesley, 2002). If you have comments about this topic, Richard can be reached at [email protected].

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.