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
-ScriptBlock
は XAML でうんうんみたいな記事を何処かで見かけたので、なんか XML が関係していそうな感じはしますが正直さっぱりわからねぇ!
PowerShell わからん