Single Instance WPF Application in .NET 3.x

2. January 2009

If you do a search on implementing a Single Instance application in WPF you'll get quite a few results. From what I've seen there are really only 2 solutions. One is really simplistic and the other offers more functionality; both of which are fairly simple to implement.

Method 1: Checking Existing Processes By Name

This is the simplest to implement. All you do is check if there is more than 1 running process with the same name as the current process.

Here's the code:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // Get Reference to the current Process
        Process thisProc = Process.GetCurrentProcess();
        // Check how many total processes have the same name as the current one
        if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1)
        {
            // If ther is more than one, than it is already running.
            MessageBox.Show("Application is already running.");
            Application.Current.Shutdown();
            return;
        }

        base.OnStartup(e);
    }
}

Even though this method is very simplistic, it doesn't offer any extended functionality unless you code it yourself. For instance, What happens if you run another instance of your app and pass in different command-line arguments? Well, with this method it just gets killed. The next example allows you to pass in and handle those new command-line arguments from the exising app instance.

Method 2: Using the WindowsFormsApplicationBase Class

The Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase is a "VB.NET" feature that is built into the .NET Framework, but it can be used from any .NET language, such as C#. You just need to add a reference to the Microsoft.VisualBasic.dll in your application.

This method even allow you to handle the command-line arguments that are passed to the "new" instance in the same manor as MS Word so you can open multiple documents while only having a single instance of your application running.

Here's a link to an example on MSDN for using this method: http://msdn.microsoft.com/en-us/library/ms771662.aspx

This method is also mentioned in "Pro WPF in C# 2008" by Matthew MacDonald from Apress. 

Also, here's the main code for using this method for reference:

namespace SingleInstanceDetection
{
    public class EntryPoint
    {
        [STAThread]
        public static void Main(string[] args)
        {
            SingleInstanceManager manager = new SingleInstanceManager();
            manager.Run(args);
        }
    }

    // Using VB bits to detect single instances and process accordingly:
    //  * OnStartup is fired when the first instance loads
    //  * OnStartupNextInstance is fired when the application is re-run again
    //    NOTE: it is redirected to this instance thanks to IsSingleInstance
    public class SingleInstanceManager : WindowsFormsApplicationBase
    {
        SingleInstanceApplication app;

        public SingleInstanceManager()
        {
            this.IsSingleInstance = true;
        }

        protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
        {
            // First time app is launched
            app = new SingleInstanceApplication();
            app.Run();
            return false;
        }

        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
        {
            // Subsequent launches
            base.OnStartupNextInstance(eventArgs);
            app.Activate();
        }
    }

    public class SingleInstanceApplication : Application
    {
        protected override void OnStartup(System.Windows.StartupEventArgs e)
        {
            base.OnStartup(e);

            // Create and show the application's main window
            MainWindow window = new MainWindow();
            window.Show();
        }

        public void Activate()
        {
            // Reactivate application's main window
            this.MainWindow.Activate();
        }
    }
}

Future Framework Support

There doesn't seem to be any "Single Instance Application" support built into WPF, and I'm not sure if MS is planning on adding any in the next version. At least these two methods work well, get the job done, and are fairly simple to implement using objects that are already backed into the .NET Framework.

WPF ,

WPF Toolkit adds Ribbon Control to .NET 3.5 SP1

28. October 2008

The first release of the new WPF Toolkit was released today. This toolkit includes a new Ribbon control as well as the following: new WPF DataGrid, DatePicker/Calendar, and VisualStateManger. The coolest feature of this Toolkit (IMO) is the new Ribbon control. In .NET 4.0 there will be a ribbon control baked in, but thanks to the WPF Toolkit we have access to utilize the new Ribbon control today in WPF with .NET 3.5 SP1!

Download the WPF Toolkit October 2008 Release: http://www.codeplex.com/wpf/Release/ProjectReleases.aspx?ReleaseId=15598

Ribbon Feature Walkthrough: http://windowsclient.net/wpf/wpf35/wpf-35sp1-ribbon-walkthrough.aspx



Here's some sample XAML markup for a complete Ribbon Tab with Button Groups defined:


<r:Ribbon>
    <r:RibbonTab Label="Banking">
        <r:RibbonGroup>
            <r:RibbonButton Command="me:AppCommands.Cut"/>
            <r:RibbonButton Command="me:AppCommands.Copy"/>
            <r:RibbonButton Command="me:AppCommands.Paste"/>
        </r:RibbonGroup>

        <r:RibbonGroup>
            <r:RibbonButton Command="me:AppCommands.AddNew"/>
            <r:RibbonButton Command="me:AppCommands.Clear" />
            <r:RibbonButton Command="me:AppCommands.Delete"/>
        </r:RibbonGroup>

        <r:RibbonGroup>
            <r:RibbonButton Command="me:AppCommands.DownloadStatements"/>
            <r:RibbonButton Command="me:AppCommands.DownloadCreditCards"/>
            <r:RibbonButton Command="me:AppCommands.Transfer"/>
        </r:RibbonGroup>
    </r:RibbonTab>
</r:Ribbon>

WPF

Add System Menu Items to WPF Window using Win32 API

27. March 2008

A couple weeks ago, I blog how to "Add System Menu Items to a Form using Windows API". Being that WPF has it's differences from Windows Forms, I began to wonder how simple or difficult this would be to do within a WPF application. As it turns out, there are a couple of extra things you need to do, but the code is pretty much the same.

This is something I used to have a code snippet for in VB6, but I haven't needed to do this in a while so I never wrote up an example in .NET. So, here's the simple code necessary to add some custom menu items to your applications System Menu within a WPF application. If you're not familiar, the System Menu is the menu that shows up if you click on the apps icon in the upper left or if you right click the app in the taskbar.

Below is a screenshot of it in action along with the complete source code in C#.

using System;
using System.Windows;
using System.Runtime.InteropServices;
using System.Windows.Interop;

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        #region Win32 API Stuff

        // Define the Win32 API methods we are going to use
        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, Int32 wFlags, Int32 wIDNewItem, string lpNewItem);

        /// Define our Constants we will use
        public const Int32 WM_SYSCOMMAND = 0x112;
        public const Int32 MF_SEPARATOR = 0x800;
        public const Int32 MF_BYPOSITION = 0x400;
        public const Int32 MF_STRING = 0x0;

        #endregion

        // The constants we'll use to identify our custom system menu items
        public const Int32 _SettingsSysMenuID = 1000;
        public const Int32 _AboutSysMenuID = 1001;

        /// <summary>
        /// This is the Win32 Interop Handle for this Window
        /// </summary>
        public IntPtr Handle
        {
            get
            {
                return new WindowInteropHelper(this).Handle;
            }
        }

        public Window1()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }

        private void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            /// Get the Handle for the Forms System Menu
            IntPtr systemMenuHandle = GetSystemMenu(this.Handle, false);

            /// Create our new System Menu items just before the Close menu item
            InsertMenu(systemMenuHandle, 5, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); // <-- Add a menu seperator
            InsertMenu(systemMenuHandle, 6, MF_BYPOSITION, _SettingsSysMenuID, "Settings...");
            InsertMenu(systemMenuHandle, 7, MF_BYPOSITION, _AboutSysMenuID, "About...");

            // Attach our WndProc handler to this Window
            HwndSource source = HwndSource.FromHwnd(this.Handle);
            source.AddHook(new HwndSourceHook(WndProc));
        }

        private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // Check if a System Command has been executed
            if (msg == WM_SYSCOMMAND)
            {
                // Execute the appropriate code for the System Menu item that was clicked
                switch (wParam.ToInt32())
                {
                    case _SettingsSysMenuID:
                        MessageBox.Show("\"Settings\" was clicked");
                        handled = true;
                        break;
                    case _AboutSysMenuID:
                        MessageBox.Show("\"About\" was clicked");
                        handled = true;
                        break;
                }
            }

            return IntPtr.Zero;
        }
    }
}

Win32API, WPF , , , ,