%ErrorLevel% and $LASTEXITCODE

This is the follow-up post of the previous PowerShell and Control-M. There is one scenario I haven't discussed: how to get the cmd.exe batch result from PowerShell.

This is not a new question but there is no clear answer you could find in Internet. Here is a post from PowerShell team: ErrorLevel equivalent, you could read that $LASTEXITCODE is designed as equivalent to %ErrorLevel%

In Cmd.exe, %ErrorLevel% is a builtin variable which indicates the success or failure of the last executable run.
$LASTEXITCODE, Contains the exit code of the last Win32 executable execution.

Problem

With the cmd.exe batch, the observed result of %ErrorLevel% and $LASTEXITCODE are different in some cases. %ErrorLevel% would not be changed for the "internal" batch command like "GOTO", but $LASTEXITCODE result will be changed. Below is one example, which is a command batch template with error handling in the old days.

[vb]
@echo off
ping %1
if %errorlevel% NEQ 0 GOTO :Error

echo %1 is reachable.
GOTO :End

:Error
echo Error happens, %1 is not reachable.

:End
[/vb]

If the batch is ran in cmd.exe, 127.0.0.1 and 999.999.999.999 are passed as parameter, expected %ErrorLevel% result 0 and 1 are returned.

20160810_batch_1

But the $LASTEXITCODE is always 0 as the ping command is not the last command in the batch file.
20160810_batch_2

How to address

We can add one exit code as the last commend in the batch file to align the $LASTEXITCODE result same as %ErrorLevel%.
Below is the updated version of the sample:
[vb]
REM Sample 2, with exit line
@echo off
ping %1
if %errorlevel% NEQ 0 GOTO :Error

echo %1 is reachable.
GOTO :End

:Error
echo Error happens, %1 is not reachable.

:End
exit /b %errorlevel%
[/vb]

Now $LASTEXITCODE result is always same as %ErrorLevel%.
20160810_batch_3

So to the PowerShell + Control-M combination, we will need to add exit /b %errorlevel% to the cmd wrapper template for case like PowerShell script recursion.

Posted by Shiyang Qiu, Aug 10, 2016