2

I wish to use Invoke-Command passing environment variables from the calling machine to the server where Invoke-Command is being executed.

I want this to work:

Invoke-Command -ComputerName MyServer-ScriptBlock {
    $env:VAR=$using:env:USERNAME
    Write-Host $env:VAR
}

But the output for this command is empty. If I do not use the $using scope modifier, and just assign the variable directly I get the expected output ("VAR").

Invoke-Command -ComputerName MyServer -ScriptBlock {
   $env:VAR="VAR"
   Write-Host $env:VAR
}

So, can I use $using with environment variables? If not, is there an easy way to pass environment variables over to the remote computer where Invoke-Command is running?

jaime
  • 2,234
  • 1
  • 19
  • 22

3 Answers3

4

One option would be to assign the environment variable to a standard variable before invoking:

$username = $env:USERNAME

Invoke-Command -ComputerName MyServer-ScriptBlock {
    $env:VAR=$using:userName
    Write-Host $env:VAR
}

Note that assigning environment variables like this ($env:VAR=<value>) won't persist once your session ends. Use the Environment.SetEnvironmentVariable() method to do that.

boxdog
  • 7,894
  • 2
  • 18
  • 27
1

I think you could use -ArgumentList. See https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/invoke-command?view=powershell-6

Invoke-Command -ComputerName MyServer -ArgumentList $env:USERNAME -ScriptBlock {
    Param ($x)

    Write-Host $x
}
Jacob Colvin
  • 2,625
  • 1
  • 17
  • 36
1

Update: The bug described below has been fixed in v7.3.


The existing answers show helpful workarounds.

It looks like you've hit a bug, present up to PowerShell 7.2.x:

The $using: scope - which is required for accessing variable values from the caller's scope in all out-of-runspace executions (see this answer) - should also support namespace variable notation (see this answer).

Thus, you should be able to pass a namespace-notation variable reference such as $env:USERNAME as $using:env:USERNAME:

  • indeed you can in the context of jobs (child-process-based background jobs started with Start-Job and thread-based jobs started with Start-ThreadJob); e.g.:

    $env:FOO = 'bar'
    # Outputs 'bar', as expected.
    Start-Job { $using:env:FOO } | Receive-Job -Wait -AutoRemoveJob
    
  • but, as of PowerShell 7.1, that doesn't work with PowerShell remoting, such as Invoke-Command -ComputerName, as in your case.

The potential bug has been reported in GitHub issue #16019.

mklement0
  • 382,024
  • 64
  • 607
  • 775