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:
- 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
If it's not a first application instance:
- Connect to server and notify it about new application instance
- 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 instanceNotifyAboutNewInstance()
- notifies already running application about new applicationNewApplicationInstanceLoaded
- event occurs when some application instance calls NotifyAboutNewInstance()
Summarizing all that I said above, the 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 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
{
[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.