0

Why would a batch script not get the error level set by executed powershell code, the first time it executes that code, but not the subsequent times?

The following is observed:

  • No error 0 [this is wrong]
  • Error as expected 2
  • Error as expected 2
  • Error as expected 2
  • Error as expected 2

In each case, the batch script below executes a small bit of embedded powershell code from within itself.

exit 2;

The first time when powershell returns, %ERRORLEVEL% is 0. The second through fifth times, %ERRORLEVEL% is 2.

<# : 
@echo off
setlocal EnableDelayedExpansion

set DEPENDENCY_DIRNAME=dependencies2

set LINKS[0]=http://www.ijg.org/files/jpegsr8c.zip
set LINKS[1]=http://downloads.xiph.org/releases/ogg/libogg-1.2.2.zip
set LINKS[2]=http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.2.zip
set LINKS[3]=http://www.libsdl.org/projects/SDL_net/release/SDL_net-1.2.7.zip
set LINKS[4]=http://www.libsdl.org/release/SDL-1.2.14.zip

SET BUILD_PATH=%~dp0
SET BUILD_SCRIPT_FILENAME=%~nx0

set FILES[0]=

SET /A IDX=0
:loop1processlinks
set LINK=!LINKS[%IDX%]!
if "!LINK!" EQU "" goto processlinkedfiles

:loop2processlink
if "!LINK!" EQU "" goto loop0continue
for /f "delims=/" %%M in ("!LINK!") do set SUBSTRING=%%M

:loop3strip
set CHAR=!LINK:~0,1!
set LINK=!LINK:~1!
if "!LINK!" EQU "" goto foundfile
if "!CHAR!" NEQ "/" goto loop3strip
goto loop2processlink

:foundfile
set FILES[%IDX%]=!SUBSTRING!
goto loop2processlink

:loop0continue
set /A IDX=!IDX!+1
goto loop1processlinks

:processlinkedfiles

set /A IDX=0
:loop_processlinkedfiles
set LINK=!LINKS[%IDX%]!
set FILE=!FILES[%IDX%]!
if "!LINK!" EQU "" goto done

if "%FILE:~-4%" EQU ".zip" (
    REM Reset error level.
    verify > nul
    more %BUILD_PATH%%0 | powershell -c -
    if %ERRORLEVEL% neq 0 (
        echo Error as expected %ERRORLEVEL%
    ) else (
        echo No error %ERRORLEVEL% [this is wrong]
    )
)

set /A IDX=!IDX!+1
goto loop_processlinkedfiles

:done
cd %BUILD_PATH%

endlocal & exit /b
#>

exit 2;
2
  • I originally deleted this question because I thought it might be the problem where the value of the last executed command is returned, rather than the argument to return. But I can't figure this one out. Commented Feb 2, 2015 at 2:31
  • Since you've already enabled delayedexpansion, try using !ERRORLEVEL! instead of %ERRORLEVEL%. Commented Feb 2, 2015 at 2:38

1 Answer 1

1
if "%FILE:~-4%" EQU ".zip" (
    REM Reset error level.
    verify > nul
    more %BUILD_PATH%%0 | powershell -c -
    if !ERRORLEVEL! neq 0 (
        echo Error as expected !ERRORLEVEL!
        CALL echo Error as expected %%ERRORLEVEL%%
    ) else (
        echo No error !ERRORLEVEL! [this is wrong]
        CALL echo No error %%ERRORLEVEL%% [this is wrong]
    )
)

Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).

Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.

Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.

Note therefore the use of CALL ECHO %%var%% which displays the changed value of var. CALL ECHO %%errorlevel%% displays, but sadly then RESETS errorlevel.

Sign up to request clarification or add additional context in comments.

1 Comment

You are correct. This question was based on a misunderstanding of when to use !var!.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.