Motivation
There is often the need to create programs for Windows that should be started only once.
Following the DRY principle repetitive code should be extracted (for example in a static helper class).
After that, all that is left to do, is wrap the core application logic in this code.
Please note, that this article does not implement and discuss the Singleton Pattern. If you are looking for implementation of the singleton pattern in C# look at Jon Skeet's excellent article.
Implementation
Mutex - a system-wide unique name
The helper utility in this article is implemented as a static class with one static method.
The class uses a named Mutex to flag system-wide, that the application is already running.
Mutex is an abbreviation of [mutual exclusion](en.wikipedia.org/wiki/Mutual_exclusion) - term used usually in a context of threading, where using mutexes is an option to prevent race conditions, when multiple threads need to access the same data.
This pattern works as expected, only if the name of the mutex object is unique - no other mutex on the system, on which the application should run, has the same name.
Example of a unique mutex name is:
_ApplicationName_GUID_
If the application name is ServicesControllerUtility
and a GUID is created with Guid.NewGuid().ToString().ToUpper()
, then a unique mutex name would look like this:
_ServiceControllerUtility_192A9AC4-1317-4340-816E-80A497EC1A83_
A detailed example how to create and use a named mutex can be found in the documentation article about Mutex Constructor.
The second parameter of the Mutex
constructor - isFirstInstance
- is the important one - if it is true, then the mutex does not yet exist and this means, that the unique code is not yet called.
mutex = new Mutex(true, uniqueApplicationDescription, out isFirstInstance);
Using Anonymous delegates to make the helper flexible
Because every application code is different, the helper class should be able to execute dynamic code. This is possible in C# using Action Delegates and Lambda expressions.
Examples of Action delegates and lambda expressions:
void Main()
{
Action<int> print = i => Console.WriteLine(i);
execute (() => Console.WriteLine("Hello, world!"));
execute (() => print(2 + 2));
}
private void execute(Action action)
{
action();
}
In this case the parameter onceInstanceAction
of the Start
method is of type Action
, and it should be used to call the code, that starts the application.
public static void Start(string uniqueApplicationDescription, string applicationTitle, Action oneInstanceAction, Action instanceNotUniqueAction = null)...
Using the helper class
The helper class creates the mutex and runs the given code once, on the first application start. The default behaviour, if the application is started again, is to show a message box to inform the user.
SingleInstance.Start("uniqueMutexName", "Application title", () =>
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ApplicationForm());
});
Sometimes this is not sufficient - for example every attempt after the first one, should be logged. For that case the class accepts a second anonymous delegate, that overrides the default behaviour if the first action is already executed:
Action customAlreadyStartedBehaviourAction = () =>
{
Logger.WriteInformation(string.Format("{0} - Application is already running.", DateTime.Now.ToShortTimeString()));
};
SingleInstance.Start("uniqueMutexName", "Application title", () =>
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ApplicationForm());
}, customAlreadyStartedBehaviourAction);
The complete helper class can be downloaded from this gist: SingleInstance.cs.
Comments and feedback are always appreciated.