While working with automation in remote computers using PowerShell, you’ll come across many scenarios where you may want to use local variables or input data in a remote session. But when you try to use a local variable in a remote session (inside the PowerShell script block), it may not work or may throw an error because the local variable doesn’t exist in the remote session. The same scenario I got in my automation which leads to writing this post.
To overcome the above scenario, PowerShell provides 3 way of methods to pass local variables to remote sessions. By using the below method, you can use them with Invoke-Command and New-PSSession to run the specific scripts inside the remote machine.
The script runs in a different scope on the remote system and it is not aware of the variables in the local session. In the example above, $local is actually $null in the remote session because it was never defined in that scope.
Note: Variables defined outside of Invoke-Command will not be available in the Invoke-Command scriptblock unless you explicitly pass them through or reference them.
- -ArgumentList parameter
- param() block
- $using scope modifier
-ArgumentList parameter & Param block
One way to pass local variables to a remote scriptblock is to use the Invoke-Command ArgumentList parameter. This parameter allows you to pass local variables to the parameter and replace local variable references in the scriptblock with placeholders.
The $args variable is an automatic variable that contains an array of the undeclared parameters or parameter values passed to a function or a scriptblock. You can access the parameters passed to the scriptblock just like elements of an array( ArgumentList parameter is an object collection. Object collections allow you to pass one or more objects at a time.) In this example, I’m just passing one.
Example: 1 Using the $args automatic variable
$username = $serviceUsername $password = $servicePwd $buildNo = $BUILD_NUMBER $userPassword = ConvertTo-SecureString -String $password -AsPlainText -Force $userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $userPassword $arguments = @("dotnet-helpers","powershell") Invoke-Command -ComputerName $iP -ScriptBlock { $args foreach ($value in $args) { write-host $value } } -credential $userCredential -ArgumentList $arguments
Note: The first parameter passed to the scriptblock is $args[0], the second is $args[1], and so on.
Example: 2 Using Param with -ArgumentList (Parameterized scriptblocks using param())
You can use param() blocks inside a function to accept parameters, but the only difference between a function and a scriptblock is that a function is named scriptblock. That means that just like in a function, we can use a param() block in a scriptblock. Then we will use this scriptblock with the Invoke-Command cmdlet and pass parameters through the -ArgumentList cmdlet.
$username = $serviceUsername
$password = $servicePwd
$buildNo = $BUILD_NUMBER
$userPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $userPassword
Invoke-Command -ComputerName $iP -ScriptBlock {
param($buildNo)
Write-host $buildNo
} -credential $userCredential -ArgumentList $buildNo
$Using Construct
From PowerShell 3, you can use local variables in remote sessions by utilizing the $Using modifier. The command uses the Using scope modifier to identify a local variable in a remote command.
$buildNo variable that is prefixed by the Using scope modifier to indicate that it was created in the local session, not in the remote session.
Example:
$buildNo = "2010" Invoke-Command -ComputerName Server01 -ScriptBlock { Write-host $Using:buildNo }
Hi There
Would love a little help on a problem i am having with passing a local variable.
I need to export a self signed certificates from 100+ servers. I was able to invoke command remotely to create the self signed certificate but exporting to PFX is giving me some trouble.
#Local variable trying to pass
$mypwd = ConvertTo-SecureString -String ‘123456’ -Force -AsPlainText
#Export command to remote server
Invoke-Command -Computername WIN10-ABCD -ScriptBlock { Get-ChildItem -Path Cert:\LocalMachine\My\30XXXXXX78CXXXXXXXXXXXX | Export-PfxCertificate -FilePath C:\D_Prereqs\WIN10-ABCD.pfx -Password $mypwd } -Credential $Credential
#Also tried with -ArgumentList $mypwd on the end
Invoke-Command -Computername WIN10-ABCD -ScriptBlock { Get-ChildItem -Path Cert:\LocalMachine\My\30XXXXXX78CXXXXXXXXXXXX | Export-PfxCertificate -FilePath C:\D_Prereqs\WIN10-ABCD.pfx -Password $mypwd } -Credential $Credential -ArgumentList $mypwd
Result: Password and ProtectTo cannot both be absent
So looks like it is not able to see the variable. Running locally works fine
Is this a limitation on passing a variable that is “ConvertTo-SecureString” ?