Single application instance using Mutex and WCF named pipes
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 thenSendNotifyMessage
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:
- 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)
- and listen for messages
- Connect to server and notify it about new application instance
- Exit from application
Using the Code
For cases described above, I've developed a small library. The main class isApplicationInstanceManager
, it can either be server or client. Here is the interface of ApplicationInstanceManager
IsInstanceAlreadyRun
- returnstrue
if one or more instances are already runningStartServer()
- should be invoked only in case if it is the first application instanceNotifyAboutNewInstance()
- notifies already running application about new applicationNewApplicationInstanceLoaded
- event occurs when some application instance callsNotifyAboutNewInstance()
ApplicationSingleInstance
class can be:
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.
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.