#問題点
Start-Jobで実行するスクリプトブロックは、呼び出し元とは別プロセスになり、外側で定義した関数(や変数)は使えません。
内側でエラー出る版
function foo($arg1){
"foo arg1="+$arg1
}
function bar($arg1){
"bar arg1="+$arg1
}
foo "outer"
bar "outer"
$code = {
foo "inner"
bar "inner"
}
$j = Start-Job -ScriptBlock $code
Wait-Job $j | Receive-Job
Remove-Job $j
output1
foo arg1=outer
bar arg1=outer
The term 'foo' is not recognized as the name of a cmdlet, function, script file
, or operable program. Check the spelling of the name, or if a path was include
d, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (foo:String) [], ParentContainsE
rrorRecordException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
The term 'bar' is not recognized as the name of a cmdlet, function, script file
, or operable program. Check the spelling of the name, or if a path was include
d, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (bar:String) [], CommandNotFound
Exception
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
内側のスクリプトブロックで使えるようにするには、Start-Jobの-InitializationScriptで関数を定義するスクリプトブロックを渡してやる必要があります。
しかし、そうすると今度は外側でその関数が使えなくなります。
外側でエラー出る版
$initScript = {
function foo($arg1){
"foo arg1="+$arg1
}
function bar($arg1){
"bar arg1="+$arg1
}
}
foo "outer"
$code = {
foo "inner"
}
$j = Start-Job -InitializationScript $initScript -ScriptBlock $code
Wait-Job $j | Receive-Job
Remove-Job $j
output2
foo : The term 'foo' is not recognized as the name of a cmdlet, function, script file, or operable p
rogram. Check the spelling of the name, or if a path was included, verify that the path is correct a
nd try again.
At C:\Users\Owner\Desktop\powershell\astest.ps1:10 char:1
+ foo "outer"
+ ~~~
+ CategoryInfo : ObjectNotFound: (foo:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
bar : The term 'bar' is not recognized as the name of a cmdlet, function, script file, or operable p
rogram. Check the spelling of the name, or if a path was included, verify that the path is correct a
nd try again.
At C:\Users\Owner\Desktop\powershell\astest.ps1:11 char:1
+ bar "outer"
+ ~~~
+ CategoryInfo : ObjectNotFound: (bar:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
foo arg1=inner
bar arg1=inner
#一応、解決策
これを回避するには以下のようにします。
一応解決版
$initScript = {
function foo($arg1){
"foo arg1="+$arg1
}
function bar($arg1){
"bar arg1="+$arg1
}
}
#全体をStart-Jobで呼び出す。
#内側で使うために、関数を定義しているScriptBlockをArgumentListで渡す
$outJob = Start-Job -InitializationScript $initScript -ArgumentList $initScript -ScriptBlock {
param($initScriptString)
#引数が文字列で渡されるので、ScriptBlock型に変換する
$initScript = [ScriptBlock]::Create($initScriptString)
foo "outer"
bar "outer"
$code = {
foo "inner"
bar "inner"
}
$j = Start-Job -InitializationScript $initScript -ScriptBlock $code
Wait-Job $j | Receive-Job
Remove-Job $j
}
Wait-Job $outJob | Receive-Job
Remove-Job $outJob
output3
foo arg1=outer
bar arg1=outer
foo arg1=inner
bar arg1=inner
あまりスマートでない気がしますね。もっといいやり方があればいいのですが。
#参考
http://stackoverflow.com/questions/7162090/how-do-i-start-a-job-of-a-function-i-just-defined