1

I am calling a .bat file from Powershell in a Microsoft Windows environment, and would like to know if the exit code was success or failure.

A problem seems to be occurring in this unusual, (although not very unusual), edge-case.

Example #1:

.\test1.bat

ECHO ON
setlocal enabledelayedexpansion
False
if !errorlevel! neq 0 exit /b !errorlevel!
echo "More text"

This works fine. False causes an error; the next line checks the status, sees a 1, and exits with code 1. The calling powershell has the correct result. echo $LASTEXITCODE is 1.

Example #2:

.\test2.bat

ECHO ON
setlocal enabledelayedexpansion
if "testing" == "testing" (
    False
    if !errorlevel! neq 0 exit /b !errorlevel!
    echo "More text"
    echo "More code"
    True
    if !errorlevel! neq 0 exit /b !errorlevel!
    echo "More code"
)

Here is the difficulty. False causes an error; the next line checks the status, sees a 1, and exits with code 1. Then, the calling powershell has an unexpected result, echo $LASTEXITCODE is 0.

Could only the batch file be modified to fix the problem?

Sam
  • 214
  • 1
  • 3
  • 7
  • How exactly do you call the batch file? – aschipfl May 27 '21 at 20:32
  • @aschipfl simply .\test1.bat – Sam May 27 '21 at 20:37
  • @KJ The reason for having the line "if !errorlevel! neq 0 exit /b !errorlevel!" is to somewhat mimic "set -e" on bash. That is, run various commands and exit right in the middle of the batch file if an error has been found. Wrapping the remainder of the file in an "else" statement (actually, many repeating else statements) would not be very elegant... – Sam May 27 '21 at 21:14
  • @KJ "give a truer snippet". Ok, I have slightly modified the original snippet. The intention is to be able to have more logic, more lines of code, and still at any point include a "check the errorlevel and exit", if something failed. – Sam May 27 '21 at 21:30
  • For your examples `If ErrorLevel 1` is probably a better fit than `if !errorlevel! neq 0`, unless there is really negative errorlevels being reported. However `False` is not a command and neither is `True`, so I'm not sure why your using different strings there. BTW what happens if you use `Exit !ErrorLevel!`, without the `/B` option. – Compo May 27 '21 at 21:36
  • @Compo, without the /B option solves it. Then, the question is, if that's the "right" solution. Why is that necessary? Maybe it's the answer... – Sam May 27 '21 at 21:38

1 Answers1

1

You're seeing problematic cmd.exe behavior when batch files are called from outside cmd.exe, such as from PowerShell, their exit codes aren't reliably relayed as cmd.exe's process exit code.

For background information, see this answer.

Workarounds:

  • Call your batch file as follows:

    cmd /c '.\test2.bat & exit'
    
  • Alternatively, if installing a third-party module (authored by me) is an option, use the ie function from the Native module (Install-Module Native), which additionally compensates for PowerShell's broken argument-passing to external programs (see this answer):

    # Assuming `Install-Module Native` was run:
    ie .\test2.bat
    
mklement0
  • 382,024
  • 64
  • 607
  • 775