35

In order to allow only a single instance of an application running I'm using mutex. The code is given below. Is this the right way to do it? Are there any flaws in the code?

How to show the already running application when user tries to open the application the second time. At present (in the code below), I'm just displaying a message that another instance is already running.

 static void Main(string[] args) { Mutex _mut = null; try { _mut = Mutex.OpenExisting(AppDomain.CurrentDomain.FriendlyName); } catch { //handler to be written } if (_mut == null) { _mut = new Mutex(false, AppDomain.CurrentDomain.FriendlyName); } else { _mut.Close(); MessageBox.Show("Instance already running"); } } 
2

5 Answers 5

24

I did it this way once, I hope it helps:

bool createdNew; Mutex m = new Mutex(true, "myApp", out createdNew); if (!createdNew) { // myApp is already running... MessageBox.Show("myApp is already running!", "Multiple Instances"); return; } 
Sign up to request clarification or add additional context in comments.

6 Comments

This code is not safe or correct: stackoverflow.com/questions/229565/…
I wish this was safe and correct. It's very simple and can be easily written without hardly any thought at all lol. +1 to the both of you, though.
@SamSaffron - Are you saying it is unsafe and incorrect only in scenarios where the mutex may be requested by multiple users OR is it unsafe and incorrect in scenarios where the mutex will only be requested by a single user as well?
I disagree with Sam's comment (and the downvotes). The code does not use mutex synchronization. Instead the mutex is only used to determine if already created by another process and will be destroyed when the process terminates including abnormal termination. I'll deem it safe and correct until seeing an explanation why it would be incorrect. Problems might be a rogue application grabbing the mutex and the process running twice within different sessions. The former is sabotage, the latter covered by the question ("user tries to open the application the second time").
One thing what is missing: GC.KeepAlive(m); Because after some time the mutex variable (m) is collected by the garbage collector and then it is possible to start another application next to the first one..
|
10
static void Main() { using(Mutex mutex = new Mutex(false, @"Global\" + appGuid)) { if(!mutex.WaitOne(0, false)) { MessageBox.Show("Instance already running"); return; } GC.Collect(); Application.Run(new Form1()); } } 

Source : http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx

2 Comments

This code is not safe or correct... stackoverflow.com/questions/229565/…
'Global' makes it global to the machine, not the running user. Thus in a server environment or over terminal services, only one user could run it at a time. I would think most users expect a single instance to mean a single instance for them.
3

I use this:

 private static Mutex _mutex; private static bool IsSingleInstance() { _mutex = new Mutex(false, _mutexName); // keep the mutex reference alive until the normal //termination of the program GC.KeepAlive(_mutex); try { return _mutex.WaitOne(0, false); } catch (AbandonedMutexException) { // if one thread acquires a Mutex object //that another thread has abandoned //by exiting without releasing it _mutex.ReleaseMutex(); return _mutex.WaitOne(0, false); } } public Form1() { if (!isSingleInstance()) { MessageBox.Show("Instance already running"); this.Close(); return; } //program body here } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (_mutex != null) { _mutex.ReleaseMutex(); } } 

Comments

1

Check out the code sample shown on this page

In short, you use the overload Mutex ctor(bool, string, out bool) which tells you via an out parameter, whether you got ownership of the Named Mutex. If you're the first instance, this out param would contain true after the ctor is called - in which case you proceed as usual. If this param is false, it means another instance has already got ownership/is running, in which case you show an error message "Another instance is already running." and then exit gracefully.

Comments

1

Use app with timeout and security settings. I used my custom class:

private class SingleAppMutexControl : IDisposable { private readonly Mutex _mutex; private readonly bool _hasHandle; public SingleAppMutexControl(string appGuid, int waitmillisecondsTimeout = 5000) { bool createdNew; var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); var securitySettings = new MutexSecurity(); securitySettings.AddAccessRule(allowEveryoneRule); _mutex = new Mutex(false, "Global\\" + appGuid, out createdNew, securitySettings); _hasHandle = false; try { _hasHandle = _mutex.WaitOne(waitmillisecondsTimeout, false); if (_hasHandle == false) throw new System.TimeoutException(); } catch (AbandonedMutexException) { _hasHandle = true; } } public void Dispose() { if (_mutex != null) { if (_hasHandle) _mutex.ReleaseMutex(); _mutex.Dispose(); } } } 

and use it:

 private static void Main(string[] args) { try { const string appguid = "{xxxxxxxx-xxxxxxxx}"; using (new SingleAppMutexControl(appguid)) { Console.ReadLine(); } } catch (System.TimeoutException) { Log.Warn("Application already runned"); } catch (Exception ex) { Log.Fatal(ex, "Fatal Error on running"); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.