PowerShellから外部EXEやcmd.exeを呼ぶときは、画面に文字が出たかではなく、終了コードを実行直後の$LASTEXITCODEで取得することが基本です。標準出力・標準エラーは実行ログとして別に保存します。

成功・失敗と標準出力の違い

外部プログラムは通常、終了コード0を成功として使うことが多いですが、意味はプログラムごとの仕様で決まります。標準出力に「OK」と表示されても終了コードが0とは限らず、エラー文が表示されても別の終了コードの扱いをするソフトもあります。PowerShellの$?は直前のコマンド成否を表しますが、外部コマンドの数値コードそのものを取得したい場合は$LASTEXITCODEを使います。

LASTEXITCODEの取得タイミング

Windows PowerShell 5.1での簡単な実例です。

& $env:ComSpec /d /c 'echo SAMPLE & exit /b 7'
$exitCode = $LASTEXITCODE   # 直後に保存する
$record = [pscustomobject]@{
    At = (Get-Date).ToString('s')
    ExitCode = $exitCode
}
$record | Export-Csv -LiteralPath '.\exit_log.csv' -NoTypeInformation -Encoding UTF8

上の例はテストのため意図的に終了コード7を返します。次の外部コマンドを実行すると$LASTEXITCODEが上書きされ得るので、必ず直後に変数へ退避します。

標準エラーと終了コードを別に記録

標準出力と標準エラーを別のファイルに保存する場合は、例えば & $env:ComSpec /d /c 'echo OK' 1> .\stdout.txt 2> .\stderr.txt のように出力先を分けられます。ログの文字コード・形式はPowerShellの版と外部プログラムに依存します。Windows PowerShell 5.1とPowerShell 7.4以降でネイティブ出力リダイレクトの扱いが異なるため、必要なら実環境で試してください。

異常終了を意図的に発生させて確認

監視や自動化では、コマンド名、実行日時、終了コード、出力先ファイルの場所をセットで記録します。終了コードが非0のときに即再実行する設計だと二重処理が起きる可能性があるため、処理内容に応じて再実行可能性を確認してください。「ログに残した」ことと「障害復旧に成功した」ことは別です。

参考資料

おすすめの記事