How to pass arguments for remote commands
When invoking remote commands, one often wants to use local values as arguments to the remote command. This post explains how to do that.
Hardcoded values
Let’s start with a simple example. Below you can see how Get-Process is invoked in a remote session when the Id parameter is set to 0:
PS> $s = New-PSSession -Computer localhost PS> Invoke-Command -Session $s -Script { Get-Process -Id 0 } Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- -------------- 0 0 0 24 0 0 Idle localhost
Passing local values
What if we want to calculate the value of the Id parameter programmatically, instead of hard-coding it to a particular integer? Well, script blocks can declare parameters and the param block can be used to pass a value to the command that is being invoked. In the following example, we declare the $processId parameter in the script block and then use the Args parameter of Invoke-Command to set the value of $processId to $pid, which is the process ID of the current Windows PowerShell process.
PS> $s = New-PSSession -ComputerName localhost PS> Invoke-Command -Session $s -Script { param($processId) Get-Process -Id $processId } -Args $pid Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- -------------- 533 13 46160 37456 198 6.07 9488 powershell localhost
The example above demonstrates that Get-Process was invoked with a process id of the local Windows PowerShell console. Invoke-Command takes whatever you pass in the Args parameter and binds it to script block’s parameters in the remote session. Note that above I simply passed in a value of a local $pid variable, but any local expression (not just a simple variable dereference) can be used instead.
Referring to remote variables
A different behavior takes place when you don’t declare script block parameters using the "param" keyword:
PS> $s = New-PSSession -ComputerName localhost PS> Invoke-Command -Session $s -Script { Get-Process -Id $pid } Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- -------------- 329 10 21216 33524 154 7.63 6596 wsmprovhost localhost
In this case $pid is an unbound variable and Windows PowerShell assumes that it refers to the $pid variable in the remote session. Therefore, as you can see Get-Process returns the process that hosts the remote session.
Magic $args variable
What happens when you use the Args parameter of Invoke-Command cmdlet, but don’t declare any parameters in the script block? Local values are still passed to the remote session and in this case are bound to the $args variable. This can save some typing:
PS> $s = New-PSSession -ComputerName localhost PS> Invoke-Command -Session $s -Script { Get-Process -Id $args[0] } -Args $pid Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- -------------- 808 46 76840 81876 596 5.05 7824 powershell localhost
Thanks,
Lukasz Anforowicz [MSFT]
Windows PowerShell Developer
Microsoft Corporation
0 comments