142

In .NET, what's the best way to prevent multiple instances of an app from running at the same time? And if there's no "best" technique, what are some of the caveats to consider with each solution?

C. Dragon 76
  • 9,882
  • 9
  • 34
  • 41

22 Answers22

175

Use Mutex. One of the examples above using GetProcessByName has many caveats. Here is a good article on the subject:

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

[STAThread]
static void Main() 
{
   using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
   {
      if(!mutex.WaitOne(0, false))
      {
         MessageBox.Show("Instance already running");
         return;
      }

      Application.Run(new Form1());
   }
}

private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
Omar Kooheji
  • 54,530
  • 68
  • 182
  • 238
ImJustPondering
  • 1,818
  • 1
  • 11
  • 3
  • 1
    Using a mutex also works for non .net code as well (although the syntax would vary) – crashmstr Sep 18 '08 at 18:28
  • 10
    Here's a slightly more filled-out version, with some good comments: http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567 – Richard Watson Jun 18 '09 at 08:33
  • 2
    @ClarkKent: Just a random string so that the Mutex name wont collide the name from another application. – jgauffin Jul 03 '13 at 15:23
  • Can this restrict to a certain number of instances too? – Alejandro del Río Jan 20 '14 at 14:02
  • this doesn't work for me, I have found the GUID from the Project Settings of application1, which I want to check. While running application1 I launch application2, which should check if application1 is running. It doesn't give me an error messagebox. – CularBytes Jan 20 '15 at 18:04
  • What do you do if you are using C#/WPF where there is no explicit main method? I don't want to explicitly declare a main since it is being auto-generated with some additional content. – yellavon Jul 10 '15 at 15:11
  • 7
    In order to have a better control while versioning or changing your app guid, you can use: `string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), true)[0]).Value;` which will get the executing assembly's guid – ciosoriog Jun 17 '16 at 17:04
  • I think an important caveat to Mutex is this: The Mutex class enforces thread identity, so a mutex can be released only by the thread that acquired it. By contrast, the Semaphore class does not enforce thread identity. A mutex can also be passed across application domain boundaries. – Sam Rueby Nov 14 '17 at 21:12
  • @yellavon create a .cs file, put in `namespace your_app {public partial class App { private void ApplicationStart(object sender, StartupEventArgs e) { ... } } }`, then set `` in `App.config` – Jamesits Jan 08 '18 at 04:19
  • Doesn't this answer depend on `Application.Run()` not returning until the application exits? I don't know how it works, but I would've thought a multithreaded application couldn't depend on something like that. `Application.Run()` is for Windows Forms, isn't it? In WPF, we're not even supposed to use the "Main" method at all, right? – Kyle Delaney Mar 29 '18 at 14:36
  • How could this be the answer!? This doesn't work at all. – zs2020 Dec 19 '18 at 16:30
  • 2
    It took me a while to realize that the above code only works, if the mutex exists as long as the instance is running. I removed the using block and changed the mutex variable to be static (or shared in vb.net). After that everything worked as expected. – Sascha Apr 08 '20 at 06:47
  • Why the GUID? Just my app name is fairly unique in the users' computer. Any special case for the GUID? – kuklei Jan 18 '21 at 17:26
28

Here is the code you need to ensure that only one instance is running. This is the method of using a named mutex.

public class Program
{
    static System.Threading.Mutex singleton = new Mutex(true, "My App Name");

    static void Main(string[] args)
    {
        if (!singleton.WaitOne(TimeSpan.Zero, true))
        {
            //there is already another instance running!
            Application.Exit();
        }
    }
}
Alex
  • 207
  • 1
  • 2
  • 11
Seibar
  • 68,705
  • 38
  • 88
  • 99
  • 2
    For a WPF application use Application.Current.Shutdown(); This method works like a charm. Thanks Terrapin. – Jeff Nov 08 '13 at 02:24
  • Here the main thing is you make mutex static. As well as in the other case GC will collect it. – Oleksii Apr 27 '15 at 12:11
  • I enjoyed the simplicity and clarity of the named Mutex. This code is concise and effective. – Chad Sep 30 '18 at 23:06
26
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
  AppLog.Write("Application XXXX already running. Only one instance of this application is allowed", AppLog.LogMessageType.Warn);
  return;
}
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
Thomas Wagner
  • 2,482
  • 1
  • 15
  • 7
  • 1
    I think that should see this:http://odetocode.com/blogs/scott/archive/2004/08/20/the-misunderstood-mutex.aspx – SubmarineX Apr 30 '14 at 08:26
  • @SubmarineX How you sure this article is correct? it is still controversy between mutex and http://www.codeproject.com/Articles/4975/Easily-Create-A-Single-Instance-Application – John Nguyen Jul 23 '14 at 07:48
  • Amazing Just perfect thanks for your time and efforts – Ahmed Mahmoud Apr 20 '15 at 08:52
  • 2
    -1 While this is the quick solution, it is also very easy to circumvent a.exe could be renamed to b.exe and both will run. + other cases where this simply wont work as intended. Use with caution! – Lars Nielsen Dec 02 '15 at 09:18
  • This does not work with mono-develop. Under windows environments it works great though. – Tono Nam Feb 11 '19 at 17:20
7

1 - Create a reference in program.cs ->

using System.Diagnostics;

2 - Put into void Main() as the first line of code ->

 if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
                return;

That's it.

user5289350
  • 71
  • 1
  • 1
7

Hanselman has a post on using the WinFormsApplicationBase class from the Microsoft.VisualBasic assembly to do this.

bdukes
  • 152,002
  • 23
  • 148
  • 175
  • I've been using that for a couple years, but am now looking to change to a Mutex-based solution. I have customers that report issues with this and I suspect it's using Remoting to do it. – Richard Watson Jun 18 '09 at 08:28
6

After trying multiple solutions i the question. I ended up using the example for WPF here: http://www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one-instance/

public partial class App : Application  
{  
    private static Mutex _mutex = null;  

    protected override void OnStartup(StartupEventArgs e)  
    {  
        const string appName = "MyAppName";  
        bool createdNew;  

        _mutex = new Mutex(true, appName, out createdNew);  

        if (!createdNew)  
        {  
            //app is already running! Exiting the application  
            Application.Current.Shutdown();  
        }  

    }          
}  

In App.xaml:

x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Kasper Jensen
  • 548
  • 5
  • 12
5

i tried all the solutions here and nothing worked in my C# .net 4.0 project. Hoping to help someone here the solution that worked for me:

As main class variables:

private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;

When you need to check if app is already running:

bool mutexCreated;
mutex = new Mutex(true, "Global\\" + appGuid, out mutexCreated);
if (mutexCreated)
    mutex.ReleaseMutex();

if (!mutexCreated)
{
    //App is already running, close this!
    Environment.Exit(0); //i used this because its a console app
}

I needed to close other istances only with some conditions, this worked well for my purpose

HypeZ
  • 4,017
  • 3
  • 19
  • 34
  • 1
    You don't need to actually acquire the mutex and release it. All you need to know is if another app has already created the object (i.e., its kernel reference count>=1). – Michael Goldshteyn Dec 12 '14 at 14:43
5

It sounds like there are 3 fundamental techniques that have been suggested so far.

  1. Derive from the Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase class and set the IsSingleInstance property to true. (I believe a caveat here is that this won't work with WPF applications, will it?)
  2. Use a named mutex and check if it's already been created.
  3. Get a list of running processes and compare the names of the processes. (This has the caveat of requiring your process name to be unique relative to any other processes running on a given user's machine.)

Any caveats I've missed?

C. Dragon 76
  • 9,882
  • 9
  • 34
  • 41
  • 3
    I don't think 3 is very efficient. I'd vote for the Mutex, used it without problems many times. I've never used item 1 not sure how that flies when you're in c#. – typemismatch Sep 18 '08 at 18:29
  • 2
    Option 1 still works with WPF it's just slightly more involved. http://msdn.microsoft.com/en-us/library/ms771662.aspx – Graeme Bradbury Feb 04 '09 at 11:01
4

Using Visual Studio 2005 or 2008 when you create a project for an executable, on the properties windows inside the "Application" panel there is a check box named “Make single instance application” that you can activate to convert the application on a single instance application.

Here is a capture of the window I'm talking of: enter image description here This is a Visual Studio 2008 windows application project.

Doliveras
  • 1,794
  • 2
  • 14
  • 30
3

This is the code for VB.Net

Private Shared Sub Main()
    Using mutex As New Mutex(False, appGuid)
        If Not mutex.WaitOne(0, False) Then
              MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        Application.Run(New Form1())
    End Using
End Sub

This is the code for C#

private static void Main()
{
    using (Mutex mutex = new Mutex(false, appGuid)) {
        if (!mutex.WaitOne(0, false)) {
            MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        Application.Run(new Form1());
    }
}
Max
  • 12,622
  • 16
  • 73
  • 101
Shruti
  • 281
  • 2
  • 4
  • 12
3

http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0—Single-Instance_Detection_and_Management

Aaron Jensen
  • 6,030
  • 1
  • 30
  • 40
2
[STAThread]
static void Main()                  // args are OK here, of course
{
    bool ok;
    m = new System.Threading.Mutex(true, "YourNameHere", out ok);

    if (! ok)
    {
        MessageBox.Show("Another instance is already running.");
        return;
    }

    Application.Run(new Form1());   // or whatever was there

    GC.KeepAlive(m);                // important!
}

From: Ensuring a single instance of .NET Application

and: Single Instance Application Mutex

Same answer as @Smink and @Imjustpondering with a twist:

Jon Skeet's FAQ on C# to find out why GC.KeepAlive matters

Sachin
  • 2,152
  • 1
  • 21
  • 43
Ric Tokyo
  • 6,577
  • 3
  • 30
  • 48
  • -1, because you fail to use a using block with the mutex, which would make the KeepAlive superfluous. And yes, I do think John Skeet got this one wrong. He doesn't elaborate why it would be wrong to Dispose the mutex in this case. –  Feb 09 '12 at 14:21
2

This article simply explains how you can create a windows application with control on the number of its instances or run only single instance. This is very typical need of a business application. There are already lots of other possible solutions to control this.

https://web.archive.org/web/20090205153420/http://www.openwinforms.com/single_instance_application.html

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Jorge Ferreira
  • 96,051
  • 25
  • 122
  • 132
2

Use VB.NET! No: really ;)

using Microsoft.VisualBasic.ApplicationServices;

The WindowsFormsApplicationBase from VB.Net provides you with a "SingleInstace" Property, which determines other Instances and let only one Instance run.

MADMap
  • 3,132
  • 3
  • 25
  • 31
1

(Note: this is a fun-solution! It works but uses bad GDI+ design to achieve this.)

Put an image in with your app and load it on startup. Hold it until the app exits. The user wont be able to start a 2nd instance. (Of course the mutex solution is much cleaner)

private static Bitmap randomName = new Bitmap("my_image.jpg");
Bitterblue
  • 13,162
  • 17
  • 86
  • 124
  • This is actually brilliant in its simplicity, and it works with pretty much any kind of file and not just images. I feel like the Mutex solution is far from "clean." It's extremely complicated and there are apparently many ways for it to fail on account of not doing it "right." It also requires a `Main()` method which goes against how WPF is supposed to work. – Kyle Delaney Mar 29 '18 at 16:53
  • This is kind of like bug using. It works but it's not made for that purpose. I wouldn't use it as a professional. – Bitterblue Apr 04 '18 at 14:32
  • Yeah, it's unfortunate we don't have a solution this effective and simple without relying on exceptions. – Kyle Delaney Apr 04 '18 at 16:18
  • Though it's not exactly a bug. It's still .NET behaving as intended. – Kyle Delaney Apr 04 '18 at 16:19
1

Simply using a StreamWriter, how about this?

System.IO.File.StreamWriter OpenFlag = null;   //globally

and

try
{
    OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
    Environment.Exit(0);
}
Divins Mathew
  • 2,908
  • 4
  • 22
  • 34
1

http://www.codeproject.com/KB/cs/SingleInstancingWithIpc.aspx

tim_yates
  • 167,322
  • 27
  • 342
  • 338
1

You have to use System.Diagnostics.Process.

Check out: http://www.devx.com/tips/Tip/20044

Thomas Jespersen
  • 11,493
  • 14
  • 47
  • 55
0

This worked for me in pure C#. the try/catch is when possibly a process in the list exits during your loop.

using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
        int procCount = 0;
        foreach (Process pp in Process.GetProcesses())
        {
            try
            {
                if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
                {
                    procCount++;                        
                    if(procCount > 1) {
                       Application.Exit();
                       return;
                    }
                }
            }
            catch { }
        }
        Application.Run(new Form1());
}
Derek Wade
  • 697
  • 8
  • 11
0

Be sure to consider security when restricting an application to a single instance:

Full article: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813

We are using a named mutex with a fixed name in order to detect whether another copy of the program is running. But that also means an attacker can create the mutex first, thereby preventing our program from running at all! How can I prevent this type of denial of service attack?

...

If the attacker is running in the same security context as your program is (or would be) running in, then there is nothing you can do. Whatever "secret handshake" you come up with to determine whether another copy of your program is running, the attacker can mimic it. Since it is running in the correct security context, it can do anything that the "real" program can do.

...

Clearly you can't protect yourself from an attacker running at the same security privilege, but you can still protect yourself against unprivileged attackers running at other security privileges.

Try setting a DACL on your mutex, here's the .NET way: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx

Aardvark
  • 8,474
  • 7
  • 46
  • 64
0

None of this answers worked for me because I needed this to work under Linux using monodevelop. This works great for me:

Call this method passing it a unique ID

    public static void PreventMultipleInstance(string applicationId)
    {
        // Under Windows this is:
        //      C:\Users\SomeUser\AppData\Local\Temp\ 
        // Linux this is:
        //      /tmp/
        var temporaryDirectory = Path.GetTempPath();

        // Application ID (Make sure this guid is different accross your different applications!
        var applicationGuid = applicationId + ".process-lock";

        // file that will serve as our lock
        var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);

        try
        {
            // Prevents other processes from reading from or writing to this file
            var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
            _InstanceLock.Lock(0, 0);
            MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);

            // todo investigate why we need a reference to file stream. Without this GC releases the lock!
            System.Timers.Timer t = new System.Timers.Timer()
            {
                Interval = 500000,
                Enabled = true,
            };
            t.Elapsed += (a, b) =>
            {
                try
                {
                    _InstanceLock.Lock(0, 0);
                }
                catch
                {
                    MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
                }
            };
            t.Start();

        }
        catch
        {
            // Terminate application because another instance with this ID is running
            Environment.Exit(102534); 
        }
    }         
Tono Nam
  • 34,064
  • 78
  • 298
  • 470
0

Normally it's done with a named Mutex (use new Mutex( "your app name", true ) and check the return value), but there's also some support classes in Microsoft.VisualBasic.dll that can do it for you.

Tomer Gabel
  • 4,104
  • 1
  • 33
  • 37