PowerShell からバッチファイルを実行して終了ステータスをとるという単純なことを実行するのに、意外にくっそはまったので、もうにどとはまらないように書いておく。
コマンドの直接実行が一番
PowerShell からコマンドを実行する場合は、start-process
などは介せず直接実行がよい。
最初こんなものを書いていたのだが、これが全くうまくいかない。下記のコードでは、Standard Outputなどが出力されない。.NET の Process を使う方法もあるが面倒なので直接実行がよさげだ。
function StopOnFailedExecution($exitCode) {
if ($exitCode -Ne 0)
{
Write-Host $exitCode
exit $exitCode
}
}
$result=start-process "cmd.exe" "/c .\Test.bat" -Wait -PassThru -NoNewWindow
$stdout=$result.StandardOutput
$stderr=$result.StandardError
Write-Host $stdout
Write-Host $stderr
StopOnFailedExecution($result.ExitCode)
Write-Host "success"
echo Hello!
exit 1
PowerShell ISE はBOMに注意
当初私は、Test.bat
の編集を PowerShell ISE
で実施していたが、これが悲劇を生んだ。PowerShell ISE は ファイルを BOM 付きで保存するのだが、cmd.exe は BOM を解釈しないようだ。下記のようなエラーになる。解決のためには、VSCode 等で
C:\Users\tsushi\Code\spike\PowerShell\TestExit.ps1
C:\Users\tsushi\Code\spike\PowerShell>echo Hello!
cmd.exe : 'echo' is not recognized as an internal or external command,
At C:\Users\tsushi\Code\spike\PowerShell\TestExit.ps1:8 char:1
+ cmd.exe /c ".\Test.bat"
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: ('echo' is no...ternal command,:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
operable program or batch file.
function StopOnFailedExecution {
if ($LASTEXITCODE)
{
Write-Host $LASTEXITCode
exit $LASTEXITCODE
}
}
cmd.exe /c ".\Test.bat"
StopOnFailedExecution($result.ExitCode)
Write-Host "success"
Result
> C:\Users\tsushi\Code\spike\PowerShell\TestExit.ps1
C:\Users\tsushi\Code\spike\PowerShell>echo Hello!
Hello!
C:\Users\tsushi\Code\spike\PowerShell>exit 1
1