February 12, 2008#

FSXGET 0.1 Beta 2 Released

logo Just released FSXGET Version 0.1 Beta 2 which contains a new feature, allowing you to select display units (meters or feet) and several bugfixes. Checks for the operating system and service pack version now as well as for SimConnect installed and instances of the application already running, to give better user feedback if the application encounters a problem at startup instead of crashing with some cryptic error message.

As always, more info and download here.

February 11, 2008#

.NET Programming: Single Instance Application

Few days ago, I did some research on how to make sure that only one instance of my .NET application will run at a time. I found there’s three ways to do so, of which two are quite common and also very stable and professional.

Solution Number 1: Using a Mutex

Just have a look at the code snippet below. This is a simple C# program with just a few lines added.

   1:  static class Program
   2:      {
   3:          static bool bFirstInstance = false;
   4:          static Mutex mtxSingleInstance = new Mutex(true, "My Mutex Name and ID String", out bFirstInstance);
   6:          /// <summary>
   7:          /// The main entry point for the application.
   8:          /// </summary>
   9:          [STAThread]
  10:          static void Main()
  11:          {
  12:              try
  13:              {
  14:                  if (!bFirstInstance)
  15:                      return;
  17:                  Application.EnableVisualStyles();
  18:                  Application.SetCompatibleTextRenderingDefault(false);
  20:                  Application.Run(new Form1());
  21:              }
  22:              finally
  23:              {
  24:                  mtxSingleInstance.Close();
  25:              }
  26:          }
  27:      }

The important lines are lines 3 and 4 and 14 and 15. First we create a mutex with any name (string) we like and try to access it. The result (whether gaining access to the mutex failed or succeeded) will be written to a boolean variable. If this is the first instance of the application, we sucessully will gain access to the mutex and bFirstInstance will be true. If it’s a second, third, … instance, the first instance of the application will already have locked the mutex and we won’t get access to it, thus bFirstInstace will be false.

We just check for the value of bFirstInstance and if it’s false, the current instance will exit immediately.

Important Note: Make sure the mutex gets closed when the first instance of your application exits (even in case it crashes and doesn’t exit normally). You can use a try / finally statement as shown above for this.

Another important thing: You should declare the mutex as a static class variable to make sure it won’t get cleaned up by garbage collection somewhere down the road. Instead of using a global static variable, you could also make use of GC.KeepAlive(mtxSingleInstance);.

For further information see the two articles here and here.

Solution Number 2: .NET Remoting

This is basically about setting up some kind of inter-process communication so one process can just shout out ‘Hey, is there someone of my kind already running?’ on some channel and other instances of this process will respond with ‘Yep, that would be me’ or whatever.

The great advantage over the method before is, that with this solution, you cannot just check for other instances already running but you can also exchange information between the two instances (like passing the command line parameters of the second instance to the first instance and let the second instance exit after this while the first instance will do the job).

Now despite this solution sounding a little bit complicated, it actually isn’t. In Visual Basic this is just activating a checkbox and in C# it’s about ten lines of code. For the Visual Basic solution, go here. For C# do the following:

  1. Add a reference to Microsoft.VisualBasic.dll to your project
  2. Add the using Microsoft.VisualBasic.ApplicationServices; statement to your main application class.
  3. Add a new class to your project, lookig like this:
    using Microsoft.VisualBasic.ApplicationServices;
    public class SingleInstanceApplication : WindowsFormsApplicationBase
        private SingleInstanceApplication()
            base.IsSingleInstance = true; 
        public static void Run(Form f, 
            StartupNextInstanceEventHandler startupHandler)
            SingleInstanceApplication app = new SingleInstanceApplication();
            app.MainForm = f;
            app.StartupNextInstance += startupHandler;
  4. Now change your main application class from this

       1:  static class Program
       2:  {
       3:      [STAThread]
       4:      static void Main()
       5:      {
       6:          Application.EnableVisualStyles();
       7:          Application.Run(new Form1());
       8:      }
       9:  }

    to this

       1:  static class Program
       2:  {
       3:      [STAThread]
       4:      static void Main()
       5:      { 
       6:          Application.EnableVisualStyles();
       7:          SingleInstanceApplication.Run(new Form1(), 
       8:              StartupNextInstanceHandler);
       9:      }
      11:      static void StartupNextInstanceHandler(
      12:          object sender, StartupNextInstanceEventArgs e)
      13:      {
      14:          // Here you can just make the current (new) instance exit or do whatever you like with the command line arguments
      15:      }
      16:  }

That’s it!

I found this idea and the code above here.

Solution Number 3: Checking the Process List

I’m not gonna go into detail here, as this shouldn’t be the preferred solution as I think. It’s just for the record. To check whether there’s already an instance of your application running, you can of course just read the systems list of processes currently running and see if your application’s in it or not!

Happy coding!