2011-01-27 4 views
5

最初の例が2番目の例と同じではないのはなぜですか?リモートコンピュータでInvoke-Commandを使用しているときにPowerShellで文字列展開が機能しない

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} 

なぜdoes't PowerShellの評価

"選択ボリューム$ volumeNum"

から

選択ボリューム2

答えて

7

Invoke-Commandを介して実行されるスクリプトブロックは、それが別のプロセスで実行され、現在の環境の状態にアクセスすることはできません。あなたのローカルコンピュータ上でコマンドを実行していれば、それはうまくいくでしょう。

文字列"select volume $volumeNum"は、リモートマシンで実行されるまで評価されていません。したがって、リモートマシン上の現在のプロセスの環境内の値を探しており、$volumeNumは定義されていません。

PowerShellには、引数をInvoke-Command経由で渡すためのメカニズムが用意されています。これは、リモートに自分のローカルマシンから作品:

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

私は同様のアプローチがあなたのために働くだろうと信じて:

Invoke-Command -ComputerName $IP -Credential $GuestVM -ScriptBlock {param($volumeNum) "select volume $volumeNum" | diskpart} -ArgumentList $volumeNum 
3

スクリプトブロックがコンパイルされます。つまり、変数参照はコンパイル時に固定されています。あなたは、実行時までスクリプトブロックの作成を延期することでこの問題を回避することができますに沿って来て他の人のための

$sb = [scriptblock]::create("select volume $volumeNum | diskpart") 
Invoke-Command -ComputerName $IP -Credential $GuestVM -ScriptBlock $sb 
2

さらに注記:GetNewClosureは同様に動作しません。

$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*" } 
関連する問題