Rick Glos Life in Portland, Oregon.

WPF Application Single Instance Detection - Only allow running your application once

14. June 2013 09:57 by Rick Glos in Programming

I have a requirement where I only want the application to be launched once.  If a subsequent launch of the application occurs, I want it to not pop-up a message to the user but to gracefully select the existing application that has already been launched, therebye preventing multiple launches of the same application.

The current application I’m targeting is a utility application (WoT Kit) I’ve written for World of Tanks that parses your battle results.  Part of the parsing process involves using an external 3rd parties site to convert the battle results from binary python in JSON.  The application uploads the binary file and gets back a string of JSON.  The guy running the website emailed me because he saw the same file getting uploaded in his logs.  Further investigation points to a user running the application more than once, most likely by accident as sometimes we get a lot of applications running.

So how is this done using a WPF application?  Further complicating this is that I’m using the Prism Patterns & Practices libraries for composite WPF applications.  I lean on this often for work related projects so this is useful in many scenarios.

Implement the Main method

First we need to take over how the application is launched.  In a WPF application, the entry point is generated for you.  If you select the option to view all files, you’ll see in your obj\$(Configuration) folder a App.g.cs file that contains the code that is the entry point.

6-14-2013 9-15-47 AM

   1:/// <summary>
   2:/// App
   3:/// </summary>
   4:public partial class App : System.Windows.Application {
   5:
   6:/// <summary>
   7:/// Application Entry Point.
   8:/// </summary>
   9:        [System.STAThreadAttribute()]
  10:        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
  11:        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
  12:public static void Main() {
  13:            WoTBattleResultsKit.App app = new WoTBattleResultsKit.App();
  14:            app.Run();
  15:        }
  16:    }

Instead we want to be in control of this bit of code.  So add a class called Startup to your project and add a Main method and just copy+paste the internal stuff from the prior Main method.

   1:class Startup
   2:    {
   3:        [STAThread]
   4:static void Main()
   5:        {
   6:            WoTBattleResultsKit.App app = new WoTBattleResultsKit.App();
   7:            app.Run();
   8:        }
   9:    }

Change your project startup object to specifically use your class.

6-14-2013 9-07-52 AM

When you F5, your application should launch just as it did previously.

Add a Activate method to your existing Application class

Next we want to open our existing class that contains the inheritance of our Application class.  For most people, and Prism users as well, this will be your App.xaml.cs file.

6-14-2013 9-38-06 AM

Crack that open and add the Activate method.

6-14-2013 9-39-24 AM

Codez:

   1:public void Activate()
   2:        {
   3: // Reactivate application's main window
   4: this.MainWindow.Activate();
   5:        }

Add the SingleInstanceManager class to encapsulate handling the single instance logic

I put this code in the Startup.cs file.  Here we are going to add a class to handle the logic for when the application is launched and when it is launched again.  We are also going to rely on the WIndowsFormsApplicationBase which is inside of Microsoft.VisualBasic library.

Here’s where you go “ermhagerd you can’t do this!  VB in my C#.”  Well get over it.  That library is in the .NET Framework, you’re not requiring the user a separate download.  Who cares if it’s VisualBasic or System.ConfigurationUtils.  It’s also the recommended implementation from MSDN (Single Instance Detection Sample).  I’ve seen other solutions using Mutex, etc – but seems unnecessarily complex – each his own.  Read all the glorious arguments for and against on StackOverflow.

Here’s the code for the entire Startup.cs with the modified Main method to use the SingleInstanceManger and the Main methods code moved inside the SingleInstanceManager.OnStartup.

   1:class Startup
   2:    {
   3:        [STAThread]
   4:static void Main(string[] args)
   5:        {
   6:            SingleInstanceManager manager = new SingleInstanceManager();
   7:            manager.Run(args);
   8:        }
   9:    }
  10: 
  11:public class SingleInstanceManager : WindowsFormsApplicationBase
  12:    {
  13:        App app;
  14: 
  15:public SingleInstanceManager()
  16:        {
  17: this.IsSingleInstance = true;
  18:        }
  19: 
  20:protected override bool OnStartup(StartupEventArgs eventArgs)
  21:        {
  22: // First time app is launched
  23:            app = new WoTBattleResultsKit.App();
  24:            app.Run();
  25: return false;
  26:        }
  27: 
  28:protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
  29:        {
  30: // Subsequent launches
  31: base.OnStartupNextInstance(eventArgs);
  32:            app.Activate();
  33:        }
  34:    }

From here you are good to go.

I’ll be using the technique for future applications and using it to update some existing applications that do this currently but do things like searching thru the processes running on the machine and throwing pop-up windows, like “You already have one of this application running" as this technique is much more user friendly.