Home > Software engineering >  How to set local variables inside remote session?
How to set local variables inside remote session?

Time:11-04

I'm running a script inside Invoke-Command. I have a global variable in my local session that got many configurations. I'm passing this object to Invoke-Command. How do I set a property inside that object in the remote session?

CodePudding user response:

What you're trying to do fundamentally cannot work:

  • A script block that runs remotely of necessity runs in a different process (on a different machine).[1]

  • You can only pass a copy of a local object to a remotely executing script block - either via Invoke-Command's -ArgumentList parameter or via a $using: reference inside the script block, but whatever modifications you make to that copy are not seen by the caller.


The solution is to output (return) the data of interest from the remotely executed script block, which you can then (re)assign to a local variable on the caller's side.

  • Note: Due to the limitations of the XML-based serialization that PowerShell employs across process / computer boundaries, what is being passed and/or returned is situationally only a (method-less) emulation of the original object; that is, type fidelity cannot be guaranteed - see this answer for background information.

For example:

# Define a local object.
$localObject = [pscustomobject] @{ Prop = 42 }

# Pass a *copy* of that object to a remotely executing script block,
# modify it there, then *output* the *modified copy* and
# assign it back to the local variable.
$localObject =
  Invoke-Command -ComputerName someServer {
    $objectCopy = $using:localObject
    # Modify the copy.
    $objectCopy.Prop  
    # Now *output* the modified copy.
   $objectCopy
 }

Note that while type fidelity is maintained in this simple example, the object returned is decorated with remoting-related properties, such as .PSComputerName - see this answer


[1] Passing objects as-is to a different runspace, so that updates to it are also seen by the caller, works only if the other runspace is a thread in the same process, such as when you use Start-ThreadJob and ForEach-Object -Parallel, and even then only if the object is an instance of a .NET reference type. Also, if there's a chance that multiple runspaces try to update the given object in parallel, you need to manage concurrency explicitly in order to avoid thread-safety issues.

  • Related