ERRORLEVEL env переменные обновляются в пакетном скрипте, но% ERRORLEVEL% не делает

744
user3377627

У меня есть следующий пакетный скрипт, который работает на FTP-сервере. Я использую планировщик, который передает 4 переменные; SouRCe, EXTension, DESTination и ZIP Directory. Это простой сценарий, который требует первых 3 переменных, но пользователь может опустить последние 4-ые, если им не нужно архивировать файлы.

@ECHO OFF  SET SRC=%1 SET EXT=%2 SET DEST=%3 SET ZIPD=%4 SET DTE=%DATE:~4,2%%DATE:~7,2%%DATE:~10,4% FOR /F "TOKENS=1-3 DELIMS=: " %%L IN ('TIME /T') DO SET hhmm=%%L%%M%  DIR /B /A:-d %SRC% IF ERRORLEVEL 1 ( ECHO *** There are no files to process. *** RC=%ERRORLEVEL% SET ERRORLEVEL=0 GOTO EXIT )  DEL /Q %SRC%\Thumbs.db  IF DEFINED ZIPD ( WZZIP %ZIPD%\%DTE%%hhmm%.zip %SRC%\*%EXT% IF ERRORLEVEL 1 ( ECHO *** WZZIP for "%SRC%\*%EXT%" failed. *** RC=%ERRORLEVEL% ECHO. GOTO EXIT ) ECHO. ECHO successfully zipped %SRC% TO %ZIPD%: %DTE%%hhmm%.zip ECHO. )  MOVE /Y %SRC%\*%EXT% %DEST% IF ERRORLEVEL 1 ( ECHO ** MOVE "%SRC%\*%EXT%" TO "%DEST%" Failed. *** RC=%ERRORLEVEL% )  :EXIT EXIT /B %ERRORLEVEL% 

Проблема, с которой я сталкиваюсь, заключается в том, что если в 8:15 утра в каталоге ничего нет (планировщик запускает его),

DIR /B /A:-d %SRC% 

дает сбой с уровнем ошибки 1. Он входит в цикл и выходит. Тест на уровень ошибки работает как

IF ERRORLEVEL 1 

и в качестве

IF NOT %ERRORLEVEL% == 0 

Проблема, с которой я сталкиваюсь, заключается в том, что при любых последующих сбоях пользовательская переменная% ERRORLEVEL% не обновляется. Вот почему я должен использовать IF ERRORLEVEL 1 для других проверок. Теперь, если WZZIP завершается ошибкой, он входит в цикл после команды, но сообщение ECHO выдает «RC = 0», даже если ERRORLEVEL должен был быть больше или равен 1, и поэтому должен был обновить% ERRORLEVEL% до кем бы это ни было. Я тестировал скрипт добавления

ECHO %ERRORLEVEL% 

до каждой другой строки, чтобы увидеть изменения, и хотя тест DIR корректно обновляет% ERRORLEVEL%, снова DEL файла thumb.db, который завершается ошибкой 99,999% времени, возвращает% ERRORLEVEL% = 0 и WZZIP, если принудительно завершается неудачей также выходит RC = 0. Пробовал SETLOCAL, SETLOCAL ENABLEEXTENSIONS и кучу других вещей, даже пытался удалить все, кроме части WZZIP, и все равно он не обновляет% ERRORLEVEL%. Это FTP-сервер, на котором мы постоянно запускаем сценарии для передачи файлов, поэтому мне было интересно, может быть, есть какой-то конфликт с другими потоками cmd, изменяющими переменную env во время выполнения моего сценария? Кроме того, большинство других сценариев были написаны не мной, и они ЛЮБЯТ использовать, SET ERRORLEVEL=whatevernumberи я знаю, что это вызывало у меня конфликты в прошлом. Мне интересно, может ли это быть виновником.

2
Read [Delayed Expansion](http://ss64.com/nt/delayedexpansion.html), google _"delayed expansion trap"_ for examples. JosefZ 7 лет назад 0

1 ответ на вопрос

1
JosefZ

Вам нужно Delayed Expansion, если вы хотите использовать переменную, которую вы изменили в том же командном блоке. ( Командный блок - это серия команд в скобках (и ).) На отложенные переменные ссылаются, используя !var!вместо %var%.

Пример :

@ECHO OFF SETLOCAL EnableExtensions EnableDelayedExpansion cmd /C exit /B 99 echo before ^(command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel! ( (call) echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel! (call ) echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel! ) echo after ^(command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel! 

Выход :

==> D:\bat\SU\1113027.bat before (command block) %errorlevel%=99 !errorlevel!=99 (inside command block) %errorlevel%=99 !errorlevel!=1 (inside command block) %errorlevel%=99 !errorlevel!=0 after (command block) %errorlevel%=0 !errorlevel!=0 

В (call)и (call )приемах, похищенные из ответа на этот Dbenham, чтобы установка ERRORLEVEL до 0 вопроса:

Если вы хотите, чтобы заставить errorlevelTo 0, то вы можете использовать это абсолютно не интуитивный, но очень эффективный синтаксис: (call ). Пробел после звонка имеет решающее значение. Если вы хотите установить errorlevelTo 1, вы можете использовать (call). Очень важно, чтобы после звонка не было места.

Похожие вопросы