[PowerShell]Start-Jobで共通の関数を使う

#問題点

Start-Jobで実行するスクリプトブロックは、呼び出し元とは別プロセスになり、外側で定義した関数(や変数)は使えません。

```ps1:内側でエラー出る版
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
```

```text: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で関数を定義するスクリプトブロックを渡してやる必要があります。
しかし、そうすると今度は外側でその関数が使えなくなります。

```ps1:外側でエラー出る版
$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
```

```text: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
```

#一応、解決策
これを回避するには以下のようにします。

```ps1:一応解決版
$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
```

```text: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