Pages

Monday 2 January 2012

WPF - Single running instance of application

Welcome!

As a win application developer, it is possible that we required to develop the singleton application - the application having only one running instance and executed without allowing user to open multiple instances.

Let's do this today in simple WPF application. Create new WPF application project. I would name it: 'SingletonApplication'. Now, lets create our 'SingletonManager' class which would contain the logic maintain singleton instance of our application.

Let's add reference to 'Microsoft.VisualBasic' dll. Now, we need to derive this class from 'WindowsFormsApplicationBase' class, which will allow us to override two important methods:
  • OnStartup - which would be called when the application's first instance is started.
  • OnStartupNextInstance - which would be called when the application's second instance started.

Now, let's add 'Main()' method to this class as this class would be our start up location for project. See the below code:
 public class SingletonManager : WindowsFormsApplicationBase
 {
  [STAThread]
  public static void Main(string[] args)
  {
   new SingletonManager().Run(args);
  }

Now, in the constructor of this class, we need to set 'IsSingleInstance' property of the parent class to 'true' - to indicate that this application is singleton application:
public SingletonManager()
{
IsSingleInstance = true;
}

It's time to handle the 'OnStartup' and 'OnStartupNextInstance' methods now. In 'OnStartup' method, we will create new instance of Application and store it in class variable for further reference. Also, we will be maintaining the start up window object - so this object can be activated when next instance is ready to run. Here is how we need to modify this method:
  public App application { get; private set; }
  MainWindow window;
  protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
  {
   application = new App();
   window = new MainWindow();
   application.Run(window);
   return false;
  }
Next, lets override the OnStartupNextInstance method:
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
  {
   base.OnStartupNextInstance(eventArgs);
   // if the window is currently minimized, then restore it.
   if (window.WindowState == WindowState.Minimized)
   {
    window.WindowState = WindowState.Normal;
   }
   window.Activate();
  }

Hmm, we are almost done now. Let's compile our project and the result should be 2 errors - stating that application has more than one entry points defined. We need to our 'SingletonManager' class as start up location for our application. Go to solution explorer, right click on our project, and click on Properties. Observe the options available under start up location:

Here, we have two start up objects: One is default App object, and the other is one which we have defined with 'Main()' method. The first one would auto-generate the code with 'Main()' method and so leading to errors. Let's select SingletonManager object as our start up object. Save the properties and compile - application should be compiles successfully now.

Go to the output directory, and run the application - first instance would run. Now, any number of time we try to run the other instance by double clicking the .exe, it would always highlight the first instance. If it's minimized, then it would be restored to normal state and then would be highlighted.

Here the full code of SingletonManager class:
using System;
using System.Windows;
using Microsoft.VisualBasic.ApplicationServices;

namespace SingletonApplication
{
 public class SingletonManager : WindowsFormsApplicationBase
 {
  [STAThread]
  public static void Main(string[] args)
  {
   new SingletonManager().Run(args);
  }

  public SingletonManager()
  {
   IsSingleInstance = true;
  }

  public App application { get; private set; }
  MainWindow window;
  protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
  {
   application = new App();
   window = new MainWindow();
   application.Run(window);
   return false;
  }
  protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
  {
   base.OnStartupNextInstance(eventArgs);
   // if the window is currently minimized, then restore it.
   if (window.WindowState == WindowState.Minimized)
   {
    window.WindowState = WindowState.Normal;
   }
   window.Activate();
  }
 }
}

Enjoy!

1 comment:

  1. This error occurred:

    Error 1 'MyApp_Desktop.App' does not contain a definition for 'Application_Startup' and no extension method 'Application_Startup' accepting a first argument of type 'MyApp_Desktop.App' could be found (are you missing a using directive or an assembly reference?) D:\MyApp\Software\MyApp_Desktop\Code\MyApp_Desktop\App.xaml

    ReplyDelete