在批处理脚本中首次执行 powershell 未设置正确的错误级别
First execution of powershell in a batch script does not set correct error level
为什么批处理脚本在第一次执行 powershell 代码时无法获得由执行的 powershell 代码设置的错误级别,但在后续时间却没有?
观察到以下情况:
- 没有错误 0 [这是错误的]
- 错误如预期 2
- 错误如预期 2
- 错误如预期 2
- 错误如预期 2
在每种情况下,下面的批处理脚本都会从自身内部执行一小段嵌入式 powershell 代码。
exit 2;
第一次powershell时returns,%ERRORLEVEL%为0。第二次到第五次,%ERRORLEVEL%为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;
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]
)
)
在块语句 (a parenthesised series of statements)
中,解析 整个 块并执行 then。块中的任何 %var%
将被该变量的值替换 在块被解析时 - 在执行块之前 - 同样的事情适用于 FOR ... DO (block)
.
因此,IF (something) else (somethingelse)
将在遇到 IF
时使用 %variables%
的值执行。
克服此问题的两种常见方法是 1) 使用 setlocal enabledelayedexpansion
并使用 !var!
代替 %var%
来访问 var
的更改值或 2)调用子例程以使用更改后的值执行进一步处理。
因此请注意 CALL ECHO %%var%%
的使用,它显示 var
的更改值。 CALL ECHO %%errorlevel%%
显示,但遗憾的是随后重置错误级别。
为什么批处理脚本在第一次执行 powershell 代码时无法获得由执行的 powershell 代码设置的错误级别,但在后续时间却没有?
观察到以下情况:
- 没有错误 0 [这是错误的]
- 错误如预期 2
- 错误如预期 2
- 错误如预期 2
- 错误如预期 2
在每种情况下,下面的批处理脚本都会从自身内部执行一小段嵌入式 powershell 代码。
exit 2;
第一次powershell时returns,%ERRORLEVEL%为0。第二次到第五次,%ERRORLEVEL%为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;
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]
)
)
在块语句 (a parenthesised series of statements)
中,解析 整个 块并执行 then。块中的任何 %var%
将被该变量的值替换 在块被解析时 - 在执行块之前 - 同样的事情适用于 FOR ... DO (block)
.
因此,IF (something) else (somethingelse)
将在遇到 IF
时使用 %variables%
的值执行。
克服此问题的两种常见方法是 1) 使用 setlocal enabledelayedexpansion
并使用 !var!
代替 %var%
来访问 var
的更改值或 2)调用子例程以使用更改后的值执行进一步处理。
因此请注意 CALL ECHO %%var%%
的使用,它显示 var
的更改值。 CALL ECHO %%errorlevel%%
显示,但遗憾的是随后重置错误级别。