Ensuring that two PowerShell scripts don't run at the same time

Tuesday, January 22, 2013 / Posted by Luke Puplett /

This quick PowerShell snippet shows how you can ensure only one instance of a script or section of a script executes at a time on a system, i.e. a server running scheduled tasks.

The script will wait while the other script or section completes. The Dispose method releases the mutex and allows any other scripts to take it and run. It should ideally be in a finally block to ensure it always gets released, although I've read that it uses a .NET critical finalizer to ensure release but I don't know if this works as well in PowerShell as it would in a proper .NET process.

    [System.Threading.Mutex]$mutant;
    try
    {
        # Obtain a system mutex that prevents more than one deployment taking place at the same time.
        [bool]$wasCreated = $false;
        $mutant = New-Object System.Threading.Mutex($true, "MyMutex", [ref] $wasCreated);        
        if (!$wasCreated)
        {            
            $mutant.WaitOne();
        }

        ### Do Work ###
    }
    finally
    {       
        $mutant.ReleaseMutex(); 
        $mutant.Dispose();
    }

7 comments:

Comment by Luke Puplett on Tuesday, January 22, 2013

Added ReleaseMutex call before dispose, since dispose doesn't seem to release. By design?

Comment by Paul Sand on Thursday, January 24, 2013

When I try to run this, I get "Method invocation failed because [System.Threading.Mutex] doesn't contain a method named 'Dispose'."

Comment by Luke Puplett on Thursday, January 24, 2013

I'll be honest Paul, I have no idea why! You could try Close() instead, it does mostly the same thing.

Comment by Paul Sand on Thursday, January 24, 2013

Good call, Luke. $mutant.Close() doesn't give me the error. My guess is something to do with the version of .NET I'm running.

Comment by Luke Puplett on Thursday, January 24, 2013

Good stuff. Funny, I can't image a world in which a Mutex was IDisposable. I don't know if you're a .NET guy but any type that creates kernel objects, or other resources that like outside of .NET, must implement IDisposable (i.e. have a Dispose method). In any case, the Close method will release everything. Cheers Paul.

Comment by Luke Puplett on Thursday, January 24, 2013

Sheeze, I can't type today. was = wasn't and like = live.

Comment by Eddy on Tuesday, February 02, 2021

https://powershell.org/forums/topic/powershell-mutex-not-working-as-expected/ This code works, but while trying to implement "single instance, exit on mutex not acquired", Close() seems to be better than Dispose()

Post a Comment