Introduction
There are a lot of articles where people describes how to create single instance application using one Mutex, but their doesn't cove 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 no, 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 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 it handle?! Here is my solution. I used WCF server or client depends if it's first instance or not. If first instance, I start server, otherwise run WCF client and notify already running instance about 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 small library. The main class is
ApplicationInstanceManager, it can either server or client. Here is interface of ApplicationInstanceManager
IsInstanceAlreadyRun - returns true if one or more instances already running
StartServer() - should be invoked only in case if it 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 possible usage of ApplicationSingleInstance class can be:
static class Program
{
private static MainForm _mainForm;
[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 encapsulate all logic and allows to start only one instance, I named it SingleInstace. SingleInstance class has only one public method - Run and takes application key and "Form" in .ctor. Here is a possible usage of SingleInstance class. SingleInsnance glass guarantee that only one application instance can be started.
static class Program
{
[STAThread]
static void Main()
{
using(SingleInstance singleInstance = new SingleInstance("MyApplication1", new Form()))
{
singleInstance.Run();
}
}
}
It only covers cases when for WinForms project, but it will not be difficult to adapt this solution for WPF project.
Thank you for reading.