Synchronized variable don't work for Remote Runspace

Tagged: 

This topic contains 6 replies, has 2 voices, and was last updated by Profile photo of ALIEN Quake ALIEN Quake 5 months, 2 weeks ago.

  • Author
    Posts
  • #44390
    Profile photo of ALIEN Quake
    ALIEN Quake
    Participant

    The code below will demonstrate usage of the Synchronized variable for Runspaces. You can use any ip/hostname for $ComputerName as long it's accessible, Powershell remoting is verified by Enter-PSSession and also you added credential to Windows Credential Manager for $ComputerName as host.

    Get-Runspace | ? Id -NE 1 | % { $_.close() ; $_.dispose() }
    $Runspace = $powerShell = $connectionInfo = $handle = $hash = $null 
    $ComputerName = '192.168.0.3'
    
    $hash = [hashtable]::Synchronized(@{})
    $hash.One = 1
    
    Write-host ('Value of $Hash.One before background runspace is {0}' -f $hash.one) -ForegroundColor Green -BackgroundColor Black
    $Uri = New-Object System.Uri("http://$($ComputerName):5985/wsman")
    $connectionInfo = New-Object System.Management.Automation.Runspaces.WSManConnectionInfo -ArgumentList $Uri
    $connectionInfo.AuthenticationMechanism = [System.Management.Automation.Runspaces.AuthenticationMechanism]::Negotiate
    $connectionInfo.OpenTimeout = 3000
    
    $Runspace = [runspacefactory]::CreateRunspace($connectionInfo) # don't work
    #$Runspace = [runspacefactory]::CreateRunspace() # works
    
    $runspace.Open()
    $runspace.SessionStateProxy.SetVariable('Hash',$hash)
    
    $powershell = [powershell]::Create()
    $powershell.Runspace = $runspace
    
    $powershell.AddScript({
        $hash.one++
    }) | Out-Null #The Out-Null at the end is used to prevent the output of the object that occurs.
    
    $handle = $powershell.BeginInvoke()
    While (-Not $handle.IsCompleted) {
        Start-Sleep -Milliseconds 100
    }
    
    $powershell.EndInvoke($handle)
    $runspace.Close()
    $powershell.Dispose()
    

    Write-host ('Value of $Hash.One after background runspace is {0}' -f $hash.one) -ForegroundColor Green -BackgroundColor Black
    As soon as I replace:

    $Runspace = [runspacefactory]::CreateRunspace()

    with

    $Runspace = [runspacefactory]::CreateRunspace($connectionInfo)

    (because I want to execute code at the remote computer), the synchronized variable $hash is not updated. Anyone know what I missing? This feature is really important and useful and I need it to make it work for remote runspaces.

    • This topic was modified 5 months, 2 weeks ago by Profile photo of ALIEN Quake ALIEN Quake.
  • #44434
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    As far as I know, you can't do that. Synchronized variables are for sharing the same objects in memory across multiple threads on the same computer. Just because we use runspaces to achieve multithreading in PowerShell locally doesn't mean that you can do all the same tricks with a remote runspace.

  • #44447
    Profile photo of ALIEN Quake
    ALIEN Quake
    Participant

    Hello, Dave. You're looking well today 😉

    That's very unfortunately for me. Without it, my script doesn't export logs. Do you know any feature or technique to achieve such synchronization between remote runspaces?

    I need a way to:
    – from the server A, run several remote runspaces, scriptblock will do some job and the errors will be stored inside [hashtable]$SynchronizedLogs as a computername = errors pairs
    – send this data to the server A (for eg to another [Array]$variable), after all runspaces are finished, export it to the file

    Any ideas?

  • #44453
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Personally, I'd just write objects to the output stream.

  • #44526
    Profile photo of ALIEN Quake
    ALIEN Quake
    Participant

    Hmmm... I've sleep with this problem and I don't want to sound like I'm not grateful for you feedback but using Write-Output is the last (and ugliest) thing which I could think of. Also it would just put text on the screen without a way to export the data to file. Good thing is that will at least allows me to see errors. I's better than nothing. Thanks anyway.

  • #44530
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I think you misunderstood me. When you write to the output stream, you can assign the results to a variable back in the calling session. It's got nothing to do with showing text on the screen. 🙂

    $results = $powershell.EndInvoke($handle)
    
    # Process your results
    
  • #44540
    Profile photo of ALIEN Quake
    ALIEN Quake
    Participant

    Now it's much more clear. That will do the job 🙂

You must be logged in to reply to this topic.