Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String expansion does not work in PowerShell when using Invoke-Command on remote computer

Why isn't the first example equivalent to the second ?

1:

$volumeNum = 2
Invoke-Command -ComputerName $IP -Credential $GuestVM -ScriptBlock {"select volume $volumeNum" | diskpart}

2:

Invoke-Command -ComputerName $IP -Credential $GuestVM -ScriptBlock {"select volume 2" | diskpart}

Why does't powershell evaluate

"select volume $volumeNum"

to

select volume 2

like image 730
Primoz Avatar asked Jan 27 '11 00:01

Primoz


2 Answers

The script block that is executed via Invoke-Command does not have access to the current environment state, it is run in a separate process. If you were running the command on your local computer it would work.

The issue is that the string "select volume $volumeNum" is not being evaluated until it is executed on the remote machine. So it is looking for the value in the environment of the current process on the remote machine and $volumeNum is not defined there.

PowerShell provides a mechanism for passing arguments via Invoke-Command. This works from my local machine to a remote:

Invoke-Command -ComputerName $ip -ScriptBlock { param($x) "hello $x" } -ArgumentList "world"

I believe a similar approach would work for you:

Invoke-Command -ComputerName $IP -Credential $GuestVM -ScriptBlock {param($volumeNum) "select volume $volumeNum" | diskpart} -ArgumentList $volumeNum
like image 105
Eric Schoonover Avatar answered Sep 18 '22 22:09

Eric Schoonover


Script blocks are compiled. That means the variable references in them are fixed at compile time. You can work around this by deferring creation of the script block until run time:

$sb = [scriptblock]::create("select volume $volumeNum | diskpart")
Invoke-Command -ComputerName $IP -Credential $GuestVM -ScriptBlock $sb
like image 33
mjolinor Avatar answered Sep 21 '22 22:09

mjolinor