Search code examples
powershellbatch-filecmderrorlevel

Using Powershell Start-Process to run a Cmd Batch file, how to read the error level from the Cmd Batch file?


Assume I have two files, script.ps1 and filename.cmd, and I run .\script.ps1 from a Powershell prompt:

script.ps1

Write-Host "About to run filename.cmd"
$proc = Start-Process -FilePath filename.cmd -NoNewWindow -Wait
Write-Host "proc: [$proc]"
Write-Host "LASTEXITCODE: [$LASTEXITCODE]

filename.cmd

@echo off
ECHO File returns ErrorLevel=1
exit /b 1

Output:

About to run filename.cmd
proc: []
LASTEXITCODE: []

Both proc and LASTEXITCODE are $null. My understanding was that somehow I could access the ErrorCode?

How do I read the failed error level (in this case 1) in my Powershell script?


Solution

  • To synchronously execute console applications, including batch files, call them directly, do not use Start-Process - see this answer.

    Therefore:

    Write-Host "About to run filename.cmd"
    # For security reasons, PowerShell requires that you explicitly
    # signal the intent to run an executable located *in the current directory*,
    # hence the need for `./` (or `.\`)
    # Only direct invocation of external programs (batch files) sets
    # the automatic $LASTEXITCODE variable.
    ./filename.cmd
    Write-Host "LASTEXITCODE: [$LASTEXITCODE]
    

    As for what you tried:

    Start-Process outputs nothing by default - except if you pass the -PassThru switch, in which case a System.Diagnostics.Process instance representing the newly started process is returned.

    Assuming you've also specified -Wait, as in your case, you can then access the returned object's .ExitCode property to determine the exit code immediately afterwards.

    Note that automatic variable $LASTEXITCODE is only set after direct invocation of external programs, as shown above.

    Therefore, if you were to use Start-Process - which is not necessary in this case, as explained above - you'd have to use the following:

    Write-Host "About to run filename.cmd"
    $proc = Start-Process -PassThru -FilePath filename.cmd -NoNewWindow -Wait
    Write-Host "proc: [$proc]"
    Write-Host "exit coe: [$($proc.ExitCode)]