Invoke-CommandでリモートPCに引数を渡す

備忘録も込めたPowerShellネタです。

PowerShellでリモートPCを操作する時の方法は以下の3つみたい。

  1. <コマンドレット> -ComputerName
    • コマンドを指定のリモートPCに対して実行。
    • 主体はコマンドを投げる側。
    • 当然だが、「-ComputerName」がそもそも存在しないコマンドも多数。
  2. Invoke-Command -ComputerName -scriptblock{Get-Service}
    • 「-scriptblock{}」をリモートPCで実行。
    • 主体はリモートPC側。
  3. Enter-PSSession -ComputerName
    • 対話モード(SSHのログインみたいな感じ)でリモートPCに接続してゴニョゴニョ。
    • 主体はリモートPC側。

1で全ての業務が片付けば問題無しだが、まぁそうは問屋がおろさない。
んで、2を使ってリモートPCの操作をスクリプト化するんだけど、スコープがリモートPC側にあるので投げる側の変数がそのまま使用できない。


リモート側に「C:\Windows」は存在するが、

$hostname = "192.168.1.2"
Invoke-Command -Computername $hostname -Scriptblock{Test-Path C:\Windows}
True

変数として渡してしまうとエラーとなる。

$hostname = "192.168.1.2"
$a = "C:\Windows"
Invoke-Command -Computername $hostname -Scriptblock{Test-Path $a}
引数が null であるため、パラメーター 'Path' にバインドできません。
    + CategoryInfo          : InvalidData: (:) [Test-Path]、ParameterBindingVal 
   idationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M 
   icrosoft.PowerShell.Commands.TestPathCommand
    + PSComputerName        : 192.168.1.2

さて、どうしましょ。。


ということで、Invoke-Commandのヘルプとにらめっこしてみると。。
あやしいのを発見。

-ArgumentList
コマンドのローカル変数の値を指定します。コマンドの変数は、リモート コン
ピューターでのコマンドの実行前にこれらの値で置換されます。値をコンマ区切
り一覧で入力します。値は、一覧されている順に変数に関連付けられます。Argu
mentList のエイリアスは "Args" です。

ArgumentList の値は、"1024" などの実際の値にすることも、"$max" などのロ
ーカル変数の参照にすることもできます。

コマンドでローカル変数を使用するには、次のコマンド形式を使用します。
{param($<名前 1>[, $<名前 2>]...)<ローカル変数を持つコマンド>} -Argument
List <値 | $ローカル変数>

"param" キーワードには、コマンドで使用するローカル変数を列挙します。Argu
mentList パラメーターには、変数を列挙した順にその値を指定します。

さっそく実行。配列で渡るということなので

$hostname = "192.168.1.2"
$a = "C:\Windows"
$b = "C:\Program Files"
Invoke-Command -Computername $hostname -Scriptblock{Test-Path $args[0];Test-Path $args[1]} -ArgumentList $a,$b
True
True

とりあえず上記を使用すれば目的は達成できそうです。


(という記事を書いてて見つけたんですが)こちらのような方法でも良いかも。
【PowerShell】Invole-Command –FilePath パラメタの魔法 - フィールドSEあがりの安納です - Site Home - TechNet Blogs