Sometimes you want to only allow for a single instance of your application and that can be accomplished by using a Mutex class. On top of that, if it’s used on a Terminal Server / Citrix, you also want to check the session id, to ensure you’re not interfering with other user’s instances or even the same user on a different connection.
EDIT: On a second read, the SID might not be needed in the mutex name, as by default the mutex is local, unless told otherwise, see note below:
http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
* * *
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
// Constants
const int SW_RESTORE = 9;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
//
// Use a Mutex to allow only one instance per session...
//
bool newInstance = true;
String mutexId = String.Format("APP={0}; SID={1}",
Assembly.GetExecutingAssembly().GetName().Name,
System.Diagnostics.Process.GetCurrentProcess().SessionId);
Mutex mutex = new System.Threading.Mutex(true, mutexId, out newInstance);
if (!newInstance) {
MessageBox.Show("Application Already Running!" + mutexId);
// Find the instance holding the mutex and restore...
Process currentProcess = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))
{
if (process.Id != currentProcess.Id &&
process.SessionId == currentProcess.SessionId)
{
// Restore window (if minimized)...
ShowWindow(process.MainWindowHandle, SW_RESTORE);
// Set foreground window...
SetForegroundWindow(process.MainWindowHandle);
break;
}
}
return;
}
//
// Run normal...
//
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
//
// Hold the mutex from being garbage collected...
//
GC.KeepAlive(mutex);
}
Resources:
thank you so much, this code help me to create a very good solution
ReplyDeleteYou might want to cut the lines:
ReplyDelete// Hold the mutex from being garbage collected...
GC.KeepAlive(mutex);
And paste them at the bottom of this method - KeepAlive() only promises to keep the object alive *until* this particular call and not after it.
Reference:
http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx
Thanks for that, I've changed the code, although I've seen it work fine before, it makes sense though to change it.
ReplyDeleteWorks great but how do I restore a window from the system tray?
ReplyDeleteIf your window was hidden, you might want to call ShowWindow(hwnd, SW_SHOW) instead or prior to SW_RESTORE.
ReplyDeleteSee if the comments at ShowWindow page help:
http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx
It helped me. great work
ReplyDeleteNavan M