In this article I will explain you how to make windows
application as singleton in c#. We can use Remoting or Mutex to make application
as singleton. We can also use Microsoft.VisualBasic assembly to make application as singleton.
I do not want to have dependency on Microsoft.Visual basic. I will go with mutex approach.
You can learn about Mutex at https://msdn.microsoft.com/en-us/library/system.threading.mutex(v=vs.110).aspx
Mutex is used for interprocess synchronization.
There are many locking constructs in .Net like Monitor and Lock. But they only
work with in process. Here we need synchronization between multiple processes
so we cannot use Monitor or lock. We have to use Mutex or Semaphore. Here is
the code to implement singleton logic.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace SingleApplication
{
static class Program
{
static Mutext cmutex = null;
internal static readonly int WM_SHOWFIRSTINSTANCE = WinFunctions.RegisterWindowMessage("WM_SHOWFIRSTINSTANCE|{0}", "Out Custom Message");
static void Main()
{
cmutex = new Mutex(false, string.Format("Global\\" + GetUniqueId); // Create global mutex, If Mutex names starts with Global then systemwide mutex is created
bool lockAccuired;
try
{
try
{
lockAccuired = cmutex.WaitOne(1000);
}
catch(AbandonedMutexException)
{
//abandoned exeption is thrown when that thread that owned the mutex does not release it. If any thread tries to accuire
//abandoned mutex then this exception is thrown. However now calling thread has accuried mutex.
lockAccuired = true;
}
catch
{
lockAccuired = false;
}
if(lockAccuired)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
WinFunctions.PostMessage((IntPtr)WinFunctions.HWND_BROADCAST,WM_SHOWFIRSTINSTANCE,IntPtr.Zero,IntPtr.Zero);
}
}
finally
{
if(lockAccuired)
{
cmutex.ReleaseMutex();
}
}
//signals garbage collector to not garbage collect this object while the application is running.
GC.KeepAlive(cmutex);
}
string GetUniqueId
{
get
{
var attributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(GuidAttribute), false);
if(attributes.Length == 0)
return string.Empty;
return ((GuidAttribute)attributes[0])).Value;
}
}
}
static public class WinFunctions
{
public const int HWND_BROADCAST = 0xffff;
public const int SW_SHOWNORMAL = 1;
//This native function is used to register message.
[DllImport("user32")]
public static extern int RegisterWindowMessage(string message);
public static int RegisterWindowMessage(string format, params object[] args)
{
string message = String.Format(format, args);
return RegisterWindowMessage(message);
}
[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImportAttribute("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImportAttribute("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static void ShowToFront(IntPtr window)
{
//Show window and display in front
ShowWindow(window, SW_SHOWNORMAL);
SetForegroundWindow(window);
}
}
}
Now in your main application form [Here Form1], i will override Form class method WinProc.
protected override void WndProc(ref Message message)
{
if (message.Msg == Program.WM_SHOWFIRSTINSTANCE)
{
ShowWindow();
}
base.WndProc(ref message);
}
Also in your main form, override Form closing event, and cancel event and show form in taskbar. So actually form is not closed when user clicks on close icon.
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
}
Also in your main form, override Form closing event, and cancel event and show form in taskbar. So actually form is not closed when user clicks on close icon.
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
}
I hope that you will now get basic idea how to implement logic to make application as singleton.