Creating (and restarting) a single-instance WPF application with SingleInstance.cs

Standard
Share

My current project presented a unique challenge. I have a need to:

  1. allow only one instance of the application to run at each workstation,
  2. notify the user that an instance is already running if a second instance is started, and
  3. be able to programmatically restart the application.

Thankfully, Microsoft has provided the SingleInstance.cs to serve these needs. Following this article on CodeProject.com was a great start. The author Arik Poznanski did an excellent job explaining the steps necessary to implement the first two requirements. I combined his techniques with information found in this article on StackOverflow.com to fully satisfy all three requirements – an application that will only allow one instance, that will notify the user that an instance is already running, and that can easily be restarted programmatically.

Start by downloading the SingleInstance.cs class and adding it to your WPF project. In your app.xaml.cs file, modify the Main() method (as specified in Arik’s article) to include the following:

using System;
using System.Threading.Tasks;
using System.Windows;
using SingleInstanceApp.Views;
using Microsoft.Shell;

namespace SingleInstanceApp
{
    public partial class App : ISingleInstanceApp
    {
        private const string Unique = "UniqueStringForSingleInstanceApp";

        [STAThread]
        public static void Main()
        {
            if (SingleInstance<App>.InitializeAsFirstInstance(Unique))
            {
                var application = new App();
                application.InitializeComponent();
                application.Run();

                // Allow single instance code to perform cleanup operations
                SingleInstance<App>.Cleanup();
            }
        }

        public App()
        {
            InitializeComponent();

            // Set shutdown mode to manual
            Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
        }

        public bool SignalExternalCommandLineArgs(System.Collections.Generic.IList<string> args)
        {
            var cv = new ConfirmationView("SingleInstanceApp is already running.", CustomConfirmationDialogButtonOptions.OK);
            cv.ShowDialog();
            Current.MainWindow.WindowState = WindowState.Maximized;
            return true;
        }
    }
}

*Note: Disregard the implementation of the ConfirmationView type. This is simply a custom MessageBox displaying text. Likewise, the CustomConfirmationDialogButtonOptions enum simply allows me to specify the buttons I want to appear in my ConfirmationView.

SingleInstance.cs defines an interface ISingleInstanceApp that we’ll implement by defining a

public bool SignalExternalCommandLineArgs(IList<string> args)

method. When a second instance of the application is started, it is this method that allows the second instance to notify the first instance that it is attempting to start.

The ability to restart the application presented a hurdle as I couldn’t simply spawn a new process, then terminate the existing one. Why, you may ask? Well, it’s the very same single-instance code that we just implemented that would prevent this from working. As soon as I attempted to spawn a second instance of my application, it would detect that an instance was already running, notify the user that it was already running, then maximize the currently running application’s window before terminating. To resolve this issue, I took the application settings idea from the StackOverflow.com article referenced above.

In a nutshell, I created an “IsRestarting” application setting with a default value of “False”. When I want to restart my app, I set this value to “True”. Then when I start my app, I check the value of the IsRestarting application setting. If it’s true, then I set it to false and wait a few seconds (to give the first instance of the application time to release its mutex after shutting down). After this brief delay, the code continues as normal. If the IsRestarting application setting if false, I simply skip the brief delay and resume processing as normal.

So there you have it – the ability to allow only one instance of your application from running, to notify the user of this event, and to restart the application programmatically.

One thought on “Creating (and restarting) a single-instance WPF application with SingleInstance.cs

Leave a Reply

Your email address will not be published. Required fields are marked *