Уровень ошибки команды «выбор» пакетного файла возвращает 0

Я пытаюсь создать пакетный файл, который выполняет другую команду «выбор» в зависимости от исполняемой версии Windows. Синтаксис команды выбора отличается в Windows 7 и Windows XP.

Команда Choice возвращает 1 для Y и 2 для N. Следующая команда возвращает правильный уровень ошибки:

Windows 7:

choice /t 5 /d Y /m "Do you want to automatically shutdown the computer afterwards "
echo %errorlevel%
if '%errorlevel%'=='1' set Shutdown=T
if '%errorlevel%'=='2' set Shutdown=F

Windows XP:

choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
echo %ERRORLEVEL%
if '%ERRORLEVEL%'=='1' set Shutdown=T
if '%ERRORLEVEL%'=='2' set Shutdown=F

Однако, когда он сочетается с командой для определения версии ОС Windows, уровень ошибки возвращает 0 перед AN после команды выбора в моих блоках кода Windows XP и Windows 7.

REM Windows XP
ver | findstr /i "5\.1\." > nul
if '%errorlevel%'=='0' (
set errorlevel=''
echo %errorlevel%
choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
echo %ERRORLEVEL%
if '%ERRORLEVEL%'=='1' set Shutdown=T
if '%ERRORLEVEL%'=='2' set Shutdown=F
echo.
)

REM Windows 7
ver | findstr /i "6\.1\." > nul
if '%errorlevel%'=='0' (
set errorlevel=''
echo %errorlevel%
choice /t 5 /d Y /m "Do you want to automatically shutdown the computer afterwards "
echo %errorlevel%
if '%errorlevel%'=='1' set Shutdown=T
if '%errorlevel%'=='2' set Shutdown=F
echo.
)

Как видите, я даже пытался очистить переменную уровня ошибки перед выполнением команды выбора, но уровень ошибки остается равным 0 после выполнения команды выбора.

Какие-нибудь советы? Спасибо!


person lbrtdy    schedule 22.12.2011    source источник


Ответы (1)


Вы столкнулись с классической проблемой: вы пытаетесь раскрыть %errorlevel% в блоке кода, заключенном в скобки. Эта форма расширения происходит во время синтаксического анализа, но вся конструкция IF анализируется сразу, поэтому значение %errorlevel% не изменится.

Решение простое - отсроченное расширение. Вам нужно SETLOCAL EnableDelayedExpansion вверху, а затем вместо этого используйте !errorlevel!. Отложенное расширение происходит во время выполнения, поэтому вы можете увидеть изменения значения в круглых скобках.

Справка для SET (SET /?) описывает проблему и решение относительно оператора FOR, но концепция остается той же.

У вас есть другие варианты.

Вы можете переместить код из тела IF в помеченные разделы кода без круглых скобок и использовать GOTO или CALL для доступа к коду. Тогда вы можете использовать %errorlevel%. Мне не нравится этот вариант, потому что CALL и GOTO относительно медленные, а код менее элегантный.

Другой вариант — использовать IF ERRORLEVEL N вместо IF !ERRORLEVEL!==N. (См. IF /?) Поскольку IF ERRORLEVEL N проверяет, если уровень ошибок >= N, вам необходимо выполнять свои тесты в порядке убывания.

REM Windows XP
ver | findstr /i "5\.1\." > nul
if '%errorlevel%'=='0' (
  choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
  if ERRORLEVEL 2 set Shutdown=F
  if ERRORLEVEL 1 set Shutdown=T
)
person dbenham    schedule 23.12.2011