My 00000010 cents

Ponderings of a Runtime Dev

Single-Instance Applications and C#

In response to a question about C# and single-instance apps I thought I'd show how to create a single-instance app in C# using the VB app model class.  The VB app model class does the heavy lifting for a number of things, including single-instance behavior.  The model was designed by the VB team and consequently has the VB customer primarily in mind.  So the VB project designer does a lot of the leg work for you if you are building a VB windows forms app and makes it easy to configure, handle the app model events, etc.  C# doesn't natively support the application model but that doesn't mean you can't use C# to enjoy the benefits--it just means you have to do a bunch of stuff manually.  Here's a bare bones single-instance C# application.  I started with a new C# Windows forms app and replaced the contents of program.cs with the following (note that you'll also need a reference to Microsoft.VisualBasic.dll):

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsApplication1
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] commandLine)
        {
            Application.SetCompatibleTextRenderingDefault(false);
            App myApp = new App();
            myApp.Run(commandLine);
        }
    }

    /// <summary>
    ///  We inherit from WindowsFormApplicationBase which contains the logic for the application model, including
    ///  the single-instance functionality.
    /// </summary>
    class App : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
    {
        public App()
        {
            this.IsSingleInstance = true; // makes this a single-instance app
            this.EnableVisualStyles = true; // C# windowsForms apps typically turn this on.  We'll do the same thing here.
            this.ShutdownStyle = Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses; // the vb app model supports two different shutdown styles.  We'll use this one for the sample.
        }

        /// <summary>
        /// This is how the application model learns what the main form is
        /// </summary>
        protected override void OnCreateMainForm()
        {
            this.MainForm = new Form1();
        }

        /// <summary>
        /// Gets called when subsequent application launches occur.  The subsequent app launch will result in this function getting called
        /// and then the subsequent instances will just exit.  You might use this method to open the requested doc, or whatever
        /// </summary>
        /// <param name="eventArgs"></param>
        protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
        {
            base.OnStartupNextInstance(eventArgs);
            System.Windows.Forms.MessageBox.Show("An attempt to launch another instance of this app was made");
        }
    }
}

In the code sample above I could have handled the myApp.StartupNextInstance event instead of overriding OnStartupNextInstance().  No biggy either way, I just went for the easy override here.  Whether you override or handle the event you'll get called on the main thread.  If you do override OnStartupNextInstance() you'll want to defer to the base class as in addition to firing the StartupNextInstance event it also sets the focus to your original instance.

When you launch this app the first time you'll see Form1.  If you launch it again while the first instance is running you'll see the message about a subsequent instance being launched as OnStartupNextInstance() gets called.  The subsequent instance will just quietly exit while the original instance keeps running.

You can get a feel for other things you can do with the app model by looking at how VB configures it.  Create a new VB windows app and go to the project designer via the solution explorer by double-clicking the "My Project" node.  If you show all files in the solution explorer, you can also examine the Application.Designer.VB file which is under the My Project / Application.myapp node.

Legal blather: Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

Published Monday, November 28, 2005 8:12 PM by Tyler Whitney
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

tomas77777 said:

Hi Tyler. I do have a problem. In starting the second time system throws exception : "Attempted to read or write protected memory WindowsFormsApplicationBase". I use C# Express Edition 2005 (final - not beta) with .NET Framework 2.0 Do you have any idee why is this happening? Thank you tomas
January 24, 2006 7:48 AM
 

Tyler Whitney said:

Tomas,
I haven't seen anything like that.  Can you post a sample of what you are doing?  Many apologies for how long it has taken me to get back to this.
April 12, 2006 2:31 PM
 

Victor Martin said:

This worked great for me.

Thanks

December 5, 2006 10:30 AM
 

Creating single Instance applications » Tech:Envelope said:

May 3, 2007 2:42 PM
 

Orlando said:

Hey tyler like what u did

I have two forms one is for splash screen the other is my main app and i us context to run them is their a way to do it with ur example? im new to the .net and c#

January 27, 2008 7:46 PM
 

Joe said:

I added "Microsoft.VisualBasic" to my References, then included "using Microsoft.VisualBasic;" at the top of the file; however, I get the error that the namespace App could not be found.

The Mutex works, but I'd rather not have it.

Code:

using System;

using System.Collections.Generic;

using System.Windows.Forms;

using Microsoft.VisualBasic;

namespace ScanIntro {

 static class Program {

   /// <summary>

   /// The main entry point for the application.

   /// </summary>

   [STAThread]

   static void Main() {

     bool isNew;

     System.Threading.Mutex mtx = new System.Threading.Mutex(true, "MyApp_Mutex", out isNew);

     if (isNew == false) {

       MessageBox.Show("This application is already running.");

       return;

     }

     Application.SetCompatibleTextRenderingDefault(false);

     App myApp = new App();

     // The type or namespace name 'App' could not be found

     myApp.Run();

   }

 }

}

February 22, 2008 1:05 PM
 

Dave Hybrid said:

Great post, really helped me understand, thanks!

September 18, 2008 2:47 PM
 

it help said:

A really well explained article and has given me a nice idea for a project!

October 20, 2008 7:08 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

© 2008 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker