PowerShellでStringからScriptBlockオブジェクトを生成(変換)する

題名の通りなのですが、どのような場面で利用するかというのと一緒に書きます。

Invoke-CommandでリモートセッションにScriptBlock型の変数をArgumentListとして渡そうとすると、途中でObjectに変換されてしまいます。

事象

まず、通常通りScriptBlockの変数を設定します。ここまでは問題ありません。

#script変数にScriptBlockを設定
PS > $script = {param($p) Write-Host "Param: $p"}
#script変数の型はScriptBlock
PS > $script.GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ScriptBlock                              System.Object
#ScriptBlock型のInvokeメソッドでスクリプトを呼び出し可能
PS > $script.Invoke("foo")
Param: foo

  

先程のscript変数を、Invoke-Commandでリモートセッションを実行する際に、引数として引き渡したらObject型に変更されてしまいます。これではInvokeメソッドも実行できません。

PS > Invoke-Command -Session $ses -ArgumentList $script -ScriptBlock {param($s) $s.GetType()}
IsPublic IsSerial Name                                     BaseType                       PSComputerName
-------- -------- ----                                     --------                       --------------
True     True     String                                   System.Object                  SERV01

 
 
 

解決策

この方法でStringからScriptBlock型を生成できます。

$scriptBlock = [Scriptblock]::Create($string)


例えば先程の例に適用すると、以下のようになります。

PS > Invoke-Command -Session $ses -ArgumentList $script -ScriptBlock {param($s) $script = [ScriptBl
ock]::Create($s); $script.GetType();$script.Invoke("foo");}
#ScriptBlock型になっているのがわかります
IsPublic IsSerial Name                                     BaseType                       PSComputerName
-------- -------- ----                                     --------                       --------------
True     False    ScriptBlock                              System.Object                  SERV01
#Invokeメソッドでスクリプトの実行も可能です。
Param: foo