How to Block Running Two Instances of the Same Program

How to block running two instances of the same program?

There are several methods you can use to accomplish only allowing one instance of your application:

Method 1: Global synchronization object or memory

It's usually done by creating a named global mutex or event. If it is already created, then you know the program is already running.

For example in windows you could do:

    #define APPLICATION_INSTANCE_MUTEX_NAME "{BA49C45E-B29A-4359-A07C-51B65B5571AD}"

//Make sure at most one instance of the tool is running
HANDLE hMutexOneInstance(::CreateMutex( NULL, TRUE, APPLICATION_INSTANCE_MUTEX_NAME));
bool bAlreadyRunning((::GetLastError() == ERROR_ALREADY_EXISTS));
if (hMutexOneInstance == NULL || bAlreadyRunning)
{
if(hMutexOneInstance)
{
::ReleaseMutex(hMutexOneInstance);
::CloseHandle(hMutexOneInstance);
}
throw std::exception("The application is already running");
}

Method 2: Locking a file, second program can't open the file, so it's open

You could also exclusively open a file by locking it on application open. If the file is already exclusively opened, and your application cannot receive a file handle, then that means the program is already running. On windows you'd simply not specify sharing flags FILE_SHARE_WRITE on the file you're opening with CreateFile API. On linux you'd use flock.

Method 3: Search for process name:

You could enumerate the active processes and search for one with your process name.

Mutex does not stop two instances of program from running at once

You can test the below code by running several instances simultaneously.

static void Main(string[] args)
{
using (var mutex = new Mutex(true, "UniqueSystemWideMutexName"))
{
//Timeout is set to zero so we don't block
if (!mutex.WaitOne(0))
{
Console.WriteLine("Program already running");
Console.ReadKey();
return;
}
Console.WriteLine("This is the only program running");
Console.ReadKey();
}
}

If you can't use Dispose for whatever reason, which the using block does for us, be sure to call ReleaseMutex.

You can also use OpenExisting to check if the mutex has already been created, but it's not necessary for this simple use case.

Prevent multiple instances of a given app in .NET?

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";

Is using a Mutex to prevent multiple instances of the same program from running safe?

In general yes this will work. However the devil is in the details.

Firstly you want to close the mutex in a finally block. Otherwise your process could abruptly terminate and leave it in a signaled state, like an exception. That would make it so that future process instances would not be able to start up.

Unfortunately though, even with a finally block you must deal with the potential that a process will be terminated without freeing up the mutex. This can happen for instance if a user kills the process through TaskManager. There is a race condition in your code that would allow for a second process to get an AbandonedMutexException in the WaitOne call. You'll need a recovery strategy for this.

I encourage you to read up on the details of the Mutex class. Using it is not always simple.


Expanding upon the race condition possibility:

The following sequence of events can occur which would cause a second instance of the application to throw:

  1. Normal process startup.
  2. Second process starts up and aquires a handle to the mutex but is switched out before the WaitOne call.
  3. Process #1 is abruptly terminated. The mutex is not destroyed because process #2 has a handle. It is instead set to an abandoned state.
  4. The second process starts running again and gets an AbanonedMutexException.

How to prevent multiple instances in Electron

There is a new API now: requestSingleInstanceLock

const { app } = require('electron')
let myWindow = null

const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore()
myWindow.focus()
}
})

// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})
}

Prevent multiple instance of a service - best approach?

Make your timer a one-shot, and re-initialize it in the elapsed event handler. For example, if you're using System.Timers.Timer, you'd initialize it like this:

myTimer.Elapsed = timer1Elapsed;
myTimer.Interval = 1000; // every second
myTimer.AutoReset = false; // makes it fire only once
myTimer.Enabled = true;

And your elapsed event handler:

void timerElapsed(object source, ElapsedEventArgs e)
{
// do whatever needs to be done
myTimer.Start(); // re-enables the timer
}

The drawback to this is that the timer doesn't fire on one second intervals. Rather, it fires one second after the last tick's processing finishes.



Related Topics



Leave a reply



Submit