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
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
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
Further note for others comming along: GetNewClosure
doesn't work as well.
$filt = "*c*"
$cl = { gci D:\testdir $filt }.GetNewClosure()
& $cl
# returns 9 items
Invoke-command -computer mylocalhost -script $cl
# returns 9 items
Invoke-command -computer mylocalhost -script { gci D:\prgs\tools\Console2 $filt }
# returns 4 items
Invoke-command -computer mylocalhost -script { gci D:\prgs\tools\Console2 "*c*" }
精彩评论