Click here to Skip to main content
15,881,882 members
Articles / Programming Languages / C#
Tip/Trick

Single application instance using Mutex and WCF named pipes

Rate me:
Please Sign up or sign in to vote.
3.50/5 (2 votes)
29 Mar 2011CPOL2 min read 16K   7   2
Another approach how to create application only with single instance using Mutex and named pipes

Introduction


There are a lot of articles where people describe how to create a single instance application using one Mutex, but ey do not cover all use cases, for example when main window is hidden in tray.

Background


I think everybody knows how to create a single instance application in C#, if not, try to Google and you will find a lot of examples where people use Mutex and then SendNotifyMessage function. This way is good only in case when the main application window is visible. If application main window is hidden, Process.MainWindowHandle always returns zero, it means that there is no window for process. Some time ago, one guy on "stackoverflow" asked how to make "single instance application" when application is hidden in tray. Of course, it's very simple to use Mutex again, but how to show window if we don't know its handle?! Here is my solution. I used WCF server or client depending on whether it is the first instance or not. If it is the first instance, I start the server, otherwise I run the WCF client and notify already running instance about the new one.

If it's a first application instance:



  1. Start WCF named pipe server inside application(of course, it can be any type of communication such as .NET Remoting, Win Sockets, etc. but I decided to use WCF)

  2. and listen for messages


If it's not a first application instance:

  1. Connect to server and notify it about new application instance

  2. Exit from application


It gives some benefits, for example: application decides what to do when new instance has been started.

Using the Code


For cases described above, I've developed a small library. The main class is

ApplicationInstanceManager, it can either be server or client. Here is the interface of ApplicationInstanceManager



  • IsInstanceAlreadyRun - returns true if one or more instances are already running

  • StartServer() - should be invoked only in case if it is the first application instance
  • NotifyAboutNewInstance() - notifies already running application about new application
  • NewApplicationInstanceLoaded - event occurs when some application instance calls NotifyAboutNewInstance()


Summarizing all that I said above, the possible usage of ApplicationSingleInstance class can be:
C#
static class Program
{
	private static MainForm _mainForm;
	/// <summary>
	/// The main entry point for the application.
	/// </summary>
	[STAThread]
	static void Main()
	{
		using (ApplicationSingleInstance singleInstance = new ApplicationSingleInstance("MyApplication"))
		{
			singleInstance.NewApplicationInstanceLoaded += new EventHandler(OnNewApplicationInstanceLoaded);
 
			if (!singleInstance.IsInstanceAlreadyRun)
			{
				singleInstance.StartServer();
				Application.EnableVisualStyles();
				Application.SetCompatibleTextRenderingDefault(false);
				_mainForm = new MainForm();
				Application.Run(_mainForm);      
			}
			else
			{
				singleInstance.NotifyAboutNewInstance();
			}
		}
	}
 
	static void OnNewApplicationInstanceLoaded(object sender, EventArgs e)
	{
		Action setTopMost = () =>
			{
				_mainForm.Visible = true;
				_mainForm.TopMost = true;
			};
 
			if (_mainForm.InvokeRequired)
				_mainForm.Invoke(setTopMost);
			else
				setTopMost();
	}
}

I also create a wrapper around ApplicationSingleInstance that encapsulates all logic and allows to start only one instance, I named it SingleInstace. SingleInstance class has only one public method - Run and take the application key and "Form" in .ctor. Here is a possible usage of SingleInstance class. SingleInstance glass guarantees that only one application instance can be started.
C#
static class Program
   {
       /// <summary>
       /// The main entry point for the application.
       /// </summary>
       [STAThread]
       static void Main()
       {
           using(SingleInstance singleInstance = new SingleInstance("MyApplication1", new Form()))
           {
               singleInstance.Run();
           }
       }
   }

It only covers cases for WinForms project, but it will not be difficult to adapt this solution for WPF project.

Thank you for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
GeneralProxy Object Pin
fmaeseele29-Mar-11 8:21
fmaeseele29-Mar-11 8:21 
GeneralFormatting Pin
Henry Minute23-Mar-11 3:11
Henry Minute23-Mar-11 3:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.