job の中で Start-Process すると死ぬ

start-job で script block を走らせて、その中で start-process して bat で stdout に何かあると死が待ち受けています。 また bat の中で python を呼び出していると追死(ついし)が待ち構えています。 2回死ね!

@rem test1.bat
echo WANWAN
python -c "print('nyoro-nyoro')"
# test1.ps1

$script = {
    echo "start"
    Start-Process -Wait -NoNewWindow -FilePath "${PWD}\test1.bat"
    echo "おわったにゃん♪"
}

Start-Job -ScriptBlock $script
# 実行
PS> .\test1.ps1
PS> Receive-job ${ID}
start

おわってないにゃん…

いろいろ検証したところ、やはり Start-Process で死んでる感じでした

解決方法

-RedirectStandardOutput のオプションを追加して stdout をファイルに落とします。

  • job は "マイドキュメント" が起点になります。ScriptBLock 内で cd してないので stdout.txt はマイドキュメントに落ちます。このサンプルは良くない
  • 場合によっては -RedirectStandardError "stderr.txt" もお忘れなく!
  • -RedirectStandardInput "emptry.txt" もあった方が死を回避出来るかも
# test1.ps1

$script = {
    echo "start"
    Start-Process -Wait -NoNewWindow -FilePath "${SCRIPT_PATH}\test1.bat" -RedirectStandardOutput "stdout.txt"
    echo "おわったにゃん♪"
}

Start-Job -ScriptBlock $script
# 実行
PS> .\test1.ps1
PS> Receive-job ${ID}
start
おわったにゃん♪

# ※ bat の結果は stdout.txt に落ちる

おわったにゃん!!

おわったにゃん!!!!

やったねタエちゃん!

たぶんだぶん

job だと stdout が無いが故に なんか調子悪いんだろうなぁとは予測するものの、ScriptBlock 直下の echo の結果は Receive-Job で得られてるんですよねぇ… さっぱりわからねぇよ Microsoft さんよォ!!

あと、ファイルに落とさず OnMemory で stdout を受け取りたい感じがとてもしますけれど、PowerShell のコマンドレットの領域だけでは出来ないんじゃないかなぁ…。 -RedirectStandardOutput に pipe handle 指定出来れば良いんですけどそんな機構では無さそうな気がするというか PowerShell レイヤーで pipe handle って何よみたいな

なお、以下のようなことは出来ません。 Start-Process は stdout に何も出力しないからです! Start-Process は子プロセスの stdout は吐きません!

# だめぽ
Start-Process -Wait -NoNewWindow -FilePath "${PWD}\test1.bat" > stdout.txt

# stdout は受け取れない(-PassThru 付与で C# の Process object が取れる
$stdout = Start-Process -Wait -NoNewWindow -FilePath "${PWD}\test1.bat"

たぶんだぶん2 - python で死んだ

bat の中で python の script を実行しています。 見ての通り stdout に出すだけなのですが… stdin が無いと Start-Prcoess が帰ってきません。 別に stdin は見てないんですが stdin の入力待ちをしているような感じで世界が止まります。 おのれほむほむ!!

というわけで -RedirectStandardInput "empty.txt" で空のファイルを stdin に与えると動いてくれました。 もし python の script で stdin から何も取ってなければ中身有っても良いと思うので、C:\Windows\System32\drivers\etc\hosts とかテキトーに与えれば良い気がしますしらんけど

空のファイルで良ければ -RedirectStandardInput "nul" とか指定したい所ですが、C# だと MS-DOS 予約デバイス名は受け入れてくれないので open 出来ず Start-Process 自体が失敗するので死にます

bat の中で python とか他の CUI プログラムを読んでおらず、bat だけで完結するようであれば -RedirectStandardInput は不要かも? python が悪いだけかこれは? 謎

たぶんだぶん3

-RedirectStandardOutput が付与されて「無くて」止まる状況において、Win10 だと State=Completed で何事も無かったかのように終わったのですが…

PS> get-job

Id  Name  PSJobTypeName   State      HasMoreData     Location
--  ----  -------------   -----      -----------     --------
55  test  BackgroundJob   Completed  True            localhost

PS> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.19041.4412
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.4412
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Win11 だと State=Failed になり Receive-job したらエラーが吐かれました。(コードは全然違うんですけど)

PS> get-job
Id   Name  PSJobTypeName   State   HasMoreData     Location
--   ----  -------------   -----   -----------     --------
112  test  BackgroundJob   Failed  True            localhost

PS> receive-job 112
[localhost] バックグラウンド プロセスからのデータを処理中にエラーが発生
しました。報告されたエラー: ノード タイプが "Text" の要素は処理できませ
ん。Element および EndElement のノード タイプのみがサポートされます。。
    + CategoryInfo          : OpenError: (localhost:String) [], PSRemo
   tingTransportException
    + FullyQualifiedErrorId : 2102,PSSessionStateBroken

PS> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.22621.2428
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.2428
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

-ScriptBlockXAML でうんうんみたいな記事を何処かで見かけたので、なんか XML が関係していそうな感じはしますが正直さっぱりわからねぇ!

PowerShell わからん