Synchronized variable don't work for Remote Runspace

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.

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.

Hello, Dave. You’re looking well today :wink:

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?

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

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.

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. :slight_smile:

$results = $powershell.EndInvoke($handle)

# Process your results

Now it’s much more clear. That will do the job :slight_smile: