Powershell Mutex not working as expected

This topic contains 2 replies, has 3 voices, and was last updated by  Stephen L. De Rudder 5 months, 1 week ago.

  • Author
    Posts
  • #54280

    Steve Flowers
    Participant

    Hello all,

    I am attempting to work with mutexes in Powershell for inter-process synchronization.

    Say I open one PS ISE and perform the below:

    $mutex = New-Object -TypeName system.threading.mutex($true, "TestMutex")
    

    Then if I open a new ISE tab or a new console session and issue the below:

    $mutex = New-Object -TypeName system.threading.mutex($true, "TestMutex")
    

    No error is thrown. I would expect an error since a mutex by this name should already exist. Furthermore, the below does not return the mutex like I would expect (when run on the new console):

    [System.Threading.Mutex]::OpenExisting("TestMutex")
    

    And finally, if I performed the below, I would expect a return code of "False" as the mutex should be busy. But I always get "True" (again, on the new console session):

    $mutex = New-Object -TypeName system.threading.mutex($false, "TestMutex")
    if ($mutex.WaitOne(5000)) { write-output "free" }
    else {write-output "mutex busy"}
    

    Any help would be appreciated.

    • This topic was modified 1 year, 1 month ago by  Steve Flowers.
  • #54282

    Don Jones
    Keymaster

    We'll see if anyone pops in with an answer, but you're a bit outside the PowerShell-verse, here. StackOverflow might be a better spot to ask. Unfortunately, I know practically nothing about .NET's implementation of mutexes to tell you if this is a problem related to PowerShell being essentially single-threaded, with its scope, the fact that PowerShell runs in the DLR, or something else entirely.

  • #70414

    Use this to determine if you get mutex:

    $CreatedMutex = ""
    $Mutex = New-Object -TypeName system.threading.mutex($true, "TestMutex", [ref] $CreatedMutex)
    if (!$CreatedMutex) {
        $Mutex.WaitOne()
    }
    # Do Stuff
    $Mutex.ReleaseMutex()
    $Mutex.Close()
    

    You also might try "Global\TestMutex" as the name to make sure it is a global mutex. You can read more about it at https://msdn.microsoft.com/en-us/library/bwe34f1k.aspx

    Timed out example:

    $CreatedMutex = ""
    $Mutex = New-Object -TypeName system.threading.mutex($true, "Global\TestMutex", [ref] $CreatedMutex)
    if (!$CreatedMutex) {
        if (!$Mutex.WaitOne(5000)) {
            throw "Timed out waiting for TestMutex"
        }
    }
    # Do Stuff
    $Mutex.ReleaseMutex()
    $Mutex.Close()
    

    Hope this helps...
    SLDR
    (Stephen L. De Rudder)

    Note: It does look like that mutexes are always created as session level mutexes even when Global\TestMutex is used. So powershells that are on different sessions will not work. I don't know if PowerShell run as admin will allow truly global mutexes to be created.

You must be logged in to reply to this topic.