2014-07-21 13 views
5

Czy ktoś może mi pomóc zrozumieć zachowanie %ERRORLEVEL% zmiennej i dlaczego to nie jest ustalona po CALL będąc wewnątrz IF, czyli linia ECHO %ERRORLEVEL%.2?IF, CALL, EXIT i% ERRORLEVEL% w .bat

@ECHO OFF 
SET ERRORLEVEL 
VERIFY > NUL 

ECHO %ERRORLEVEL%.0 
IF ERRORLEVEL 1 ECHO SNAFU 

IF %ERRORLEVEL% == 0 (
    ECHO %ERRORLEVEL%.1 
    CALL :FOO 
    ECHO %ERRORLEVEL%.2 
    IF ERRORLEVEL 42 ECHO 42.3 
) 

GOTO :EOF 

:FOO 
    EXIT /B 42 
GOTO :EOF 

STDOUT

C:\Users\Ilya.Kozhevnikov\Dropbox>foo.bat 
Environment variable ERRORLEVEL not defined 
0.0 
0.1 
0.2 
42.3 

Jednak bez IF zmienna %ERRORLEVEL% jest ustawiony prawidłowo.

@ECHO OFF 
SET ERRORLEVEL 
VERIFY > NUL 

ECHO %ERRORLEVEL%.0 
IF ERRORLEVEL 1 ECHO SNAFU 

REM IF %ERRORLEVEL% == 0 (
    ECHO %ERRORLEVEL%.1 
    CALL :FOO 
    ECHO %ERRORLEVEL%.2 
    IF ERRORLEVEL 42 ECHO 42.3 
REM) 

GOTO :EOF 

:FOO 
    EXIT /B 42 
GOTO :EOF 

STDOUT

C:\Users\Ilya.Kozhevnikov\Dropbox>foo.bat 
Environment variable ERRORLEVEL not defined 
0.0 
0.1 
42.2 
42.3 
+0

możliwe duplikat [Windows partii ustawić wewnątrz jeśli nie pracuje] (http : //stackoverflow.com/questions/9102422/windows-batch-set-inside-if-not-working) – Laf

+0

Zobacz pytanie, które oznaczyłem jako duplikat. To wyjaśnia dokładnie, co dzieje się z twoim skryptem i co musisz zrobić, aby rozwiązać problem. – Laf

Odpowiedz

8

Gdy parser cmd odczytuje wiersz lub blok linii (kod wewnątrz nawiasów), wszystkie zmienne odczyty są zastępowane wartością wewnątrz zmiennej przed rozpoczęcie wykonywania kodu. Jeśli wykonanie kodu w bloku zmienia wartość zmiennej, ta wartość nie może być widoczna z tego samego bloku, ponieważ operacja odczytu na zmiennej nie istnieje, została zastąpiona wartością w zmiennej

Aby rozwiązać ten problem, należy włączyć opcję opóźnionego rozszerzenia i, w razie potrzeby, zmienić składnię z %var% na !var!, wskazując dla analizatora składni, że operacja odczytu musi być opóźniona, aż do wykonania polecenia.

@ECHO OFF 

setlocal enabledelayedexpansion 

SET ERRORLEVEL 
VERIFY > NUL 

ECHO %ERRORLEVEL%.0 
IF ERRORLEVEL 1 ECHO SNAFU 

IF %ERRORLEVEL% == 0 (
    ECHO !ERRORLEVEL!.1 
    CALL :FOO 
    ECHO !ERRORLEVEL!.2 
    IF ERRORLEVEL 42 ECHO 42.3 
) 

GOTO :EOF 

:FOO 
    EXIT /B 42 
GOTO :EOF 
+1

Dzięki, nie zdawałem sobie sprawy ze składni "!!". –

1

MC ND już odpowiedział na pytanie.

Oto alternatywny kod pokazujący rozszerzoną i opóźnioną rozbudowę o ERRORLEVEL.

@ECHO OFF 
SETLOCAL ENABLEDELAYEDEXPANSION 
VERIFY > NUL 

ECHO !ERRORLEVEL!.0 delayed 
ECHO %ERRORLEVEL%.0 expanded 
IF ERRORLEVEL 1 ECHO SNAFU 

IF !ERRORLEVEL! == 0 (
    ECHO !ERRORLEVEL!.1 delayed 
    ECHO %ERRORLEVEL%.1 expanded 
    CALL :FOO 
    ECHO !ERRORLEVEL!.2 delayed 
    ECHO %ERRORLEVEL%.2 expanded 
) 
ENDLOCAL 
GOTO :EOF 

:FOO 
    EXIT /B 42 
GOTO :EOF 

Microsoft opisuje zachowanie opóźnionego ekspansji pomocą polecenia set który można odczytać w oknie wiersza polecenia po wprowadzeniu set /? lub help set