情報を探すのに苦労したので、ココにメモ。
概要
Start-Process
で$MyInvocation
を使用しているスクリプトを実行すると、$MyInvocation
がnullになる。
スクリプトを実行 & 戻り値取得 & 実行スクリプト内でスクリプト自身のパス取得、をやろうとするとハマる。
Power Shell v3.0で確認。参照元情報ではPower Shell v2.0で確認。
発生例
Script2.ps1
はスクリプトのパス取得に$MyInvocation
を使用しており、Script1.ps1
からScript2.ps1
をStart-Job
で実行する。
Script1.ps1
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }
$job = Start-Job -FilePath "$(PSScriptRoot)\Script2.ps1"
$job | Wait-Job | Receive-Job
Script2.ps1
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }
Trap { throw $_ }
"Invoking Script2.ps1"
Script1.ps1
を実行すると、エラーになる。
Receive-Job : Cannot bind argument to parameter 'Path' because it is an empty string.
At C:\dev\Script1.ps1:4 char:30
+ $job | Wait-Job | Receive-Job <<<<
+ CategoryInfo : InvalidData: (:String) [Split-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.SplitPathCommand
Script2.ps1
の$MyInvocation.ScriptName
がnullになっている。
スコープがはずれてしまう。
対処法
ScriptBlockを作成した上で呼び出す。
分かりやすくと
$script2 = "$(PSScriptRoot)\Script2.ps1"
$scriptBlock = [ScriptBlock]::Create($script2)
$job = Start-Job -ScriptBlock $scriptBlock
$job | Wait-Job | Receive-Job
実際はこんな感じで
$job = Start-Job -ScriptBlock ([ScriptBlock]::Create("$(PSScriptRoot)\Script2.ps1"))
$job | Wait-Job | Receive-Job
・・・こんなの絶対わかんねぇよ(;´Д`)