共用方式為


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 https://www.microsoft.com/info/cpyright.htm

Comments

  • Anonymous
    January 23, 2006
    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

  • Anonymous
    April 12, 2006
    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.

  • Anonymous
    December 05, 2006
    This worked great for me. Thanks

  • Anonymous
    May 03, 2007
    PingBack from http://www.techenvelope.com/2007/05/03/creating-single-instance-applications/

  • Anonymous
    January 27, 2008
    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#

  • Anonymous
    February 22, 2008
    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();    }  } }

  • Anonymous
    September 18, 2008
    Great post, really helped me understand, thanks!

  • Anonymous
    October 20, 2008
    A really well explained article and has given me a nice idea for a project!

  • Anonymous
    February 27, 2009
    Neither one of these methods work. VC 2008 C# VS 2008 Winform. Vista Buisness Pro Multile Apps are run with no warning, shutdown, nothing.

  • Anonymous
    February 28, 2009
    "no luck" - can you provide me some details on what your app looks like?  Not much to go on to try to diagnose the reason for the trouble...

  • Anonymous
    February 28, 2009
    Hey Joe, so where did you define the App class at?  Is the text you provide from another file?  We don't define App in the VB runtime.  The code I provided defines a class App which inherits from the class in the vb runtime that knows how to do single-instance.  You'd need access to that class to make your app work. The vb runtime class I inherit from in my example takes care of the mutex, and does work to secure it as well.

  • Anonymous
    May 21, 2009
    Is there a similar solution for a C# Console-based app? (1) I need to ensure only one instance, AND, (2) Tell first instance when a second instance has tried to start I'm going around in circles:

  • Windows message puming (need Windows form)
  • VB solution (need Windows form)
  • Remoting needs complex common object (DLL), client and server
  • Named pipes and channels
  • WM_COPYDATA, shared memory and serializable objects
  • Sockets and pipes
  • Even WFC Is there not one easy solution fot C# and console apps???????????
  • Anonymous
    June 08, 2009
    PingBack from http://jointpainreliefs.info/story.php?id=510

  • Anonymous
    July 05, 2009
    I have implemented above method on application which is already using .net remoting in client server environment. But when trying to connect to server on first instance, got following error. Authenicated Failure Unable to read data from the transport connection: The connection was closed

  • Anonymous
    February 18, 2010
    The comment has been removed