Почему значение ErrorLevel не обновляется?

1969
PsychoData

Я пытаюсь написать подпрограмму в пакетном режиме, чтобы определить, установлен ли на компьютере режим Deep Freeze или он надежно заморожен. (Для тех, кто не знает, Deep Freeze - это программа, которая обычно используется для восстановления / предотвращения и изменения диска в операционной системе.) Dfc.exe - это файл, который можно установить при помощи глубокой заморозки. Возвращает 0 в случае размораживания или 1 в случае замораживания

По сути, я думал, что бессмысленно запускать скрипты, которые устанавливают определенные вещи, если компьютер завис. Сначала я проверяю, установлен ли dfc.exe, затем я пытаюсь проверить, не оттаяло ли оно, но проблема в том, что по какой-то причине возвращаемое значение dfc не обновляется, когда я проверяю уровень ошибки во второй раз.

Кто-нибудь знает, почему я не вижу возвращаемого значения второй проверки ErrorLevel ( в строке 41 ), которую я также включил в код ниже.

РЕДАКТИРОВАТЬ: Добавлен Psuedocode для моего мыслительного процесса перед кодом.

::Point1 IF Dfc.exe is present then ( ::Point2 If "dfc get /ISFROZEN" returns FROZEN then ( ::Point3 Write out to file so we can know that something was skipped,  goto EOF to close out of script and avoid wasting cycles installing ) ::Point4  ::Deep freeze is installed, but thawed or it would have gotten caught in the "FROZEN" IF ::Fall through out of outer IF without running anything else ) ::Point5  GOTO (Return to where we left to check if we were wasting time with a label)  

Код ниже здесь

@ECHO Off ::CheckForDF here ECHO We will now test for DeepFreeze ether not installed or is thawed Pause  ECHO.  set flagfile=C:\testjava.txt ::Flagfile variable should already be defined before calling this function Goto :CheckForDF :DFNotFrozen ECHO DeepFreeze wasn't installed or is currently thawed ECHO **Continue with the rest of the script**  ECHO. PAUSE  GOTO:eof        ::*************************** ::********Subroutines******** ::***************************   :CheckForDF WHERE dfc >nul 2>&1   ::ErrorLEvel 0 means file was found, which means DF is installed  IF %ERRORLEVEL% EQU 0 ( dfc get /ISFROZEN ECHO %errorlevel% ::ErrorLevel 0 - THAWED and ready to install  ::ErrorLevel 1 - FROZEN and pointless to try  IF %errorlevel% EQU 1 (  ::Echo out what WOULD have been installed to a file so we could check that the :: script still ran (and get an idea of how bad we need to unfreeze and log into each computer)  ECHO %flagfile% %date%%time% >> C:\BRCCIT\ScriptsSkippedByDeepFreeze.txt ECHO ****DeepFreeze is currently frozen****  ECHO. PAUSE  ::Else - DeepFreeze is thawed. return to normal script goto :EOF  )  ::DeepFreeze is thawed, but is installed. We'll just fall through to the not installed result )  ::DeepFreeze Installation not found. Okay to return to normal script ECHO DeepFreeze is not installed goto :DFNotFrozen 

ОБНОВЛЕНИЕ: я отказался от вложенных IF и вернулся к GOTOs и Labels. Это не так красиво, но этот код на самом деле работает и буквально за десять минут. Я отступил, чтобы создать визуальный эффект искусственного «вложения»

@ECHO Off ::CheckForDF here ECHO We will now test for DeepFreeze ether not installed or is thawed Pause  ECHO.  set flagfile=C:\testjava.txt ::Flagfile variable should already be defined before calling this function Goto :CheckForDF :DFNotFrozen ECHO DeepFreeze wasn't installed or is currently thawed ECHO **Continue with the rest of the script**  ECHO. PAUSE  GOTO:eof    ::*************************** ::********Subroutines******** ::***************************    :CheckForDF WHERE dfc >nul 2>&1  IF %ErrorLevel% EQU 0 Goto :DFInstalled ::ELSE - DF Not found  GOTO :ReturnToScript   :DFInstalled ::DFC.exe get /ISFROZEN Call ExitWithSpecifiedCode.bat 1 ::If Frozen IF %ErrorLevel% EQU 1 GOTO DFFrozen ::If Thawed IF %ErrorLevel% EQU 0 GOTO ReturnToScript   :DFFrozen ECHO %flagfile% %date%%time% >> C:\BRCCIT\ScriptsSkippedByDeepFreeze.txt ECHO ****DeepFreeze is currently frozen****  ECHO. PAUSE ::Exit Script Execution goto :EOF  :ReturnToScript ECHO ReturnToScript PAUSE GOTO (Return to script execution) 
1
Попробуйте проверить с 'errorlevel 1' вместо использования расширения среды. Pablo Montilla 9 лет назад 0
«IF errorlevel 0» говорит «Синтаксис команды неверен» и завершает работу скрипта. В частности, я заменил IF, который проверяет, был ли найден файл между точками Point1 и Point2. (Я также заменил другой, но сценарий потерпел крах, прежде чем он туда попал) PsychoData 9 лет назад 0
Я думаю, что синтаксис `if errorlevel n` проходит, когда errorlevel больше или равен n. Поэтому `if errorlevel 0` не имеет смысла, но для той части, которая выполняет проверку` if errorlevel 1`, должно работать. Pablo Montilla 9 лет назад 1
@PabloMontilla ааа, нюанс, который я пропустил. Один момент. PsychoData 9 лет назад 0
Я думаю, что ему не понравился уровень ошибки 0, я вернулся к тому, как проверял это. Похоже, проверка уровня ошибки, который (ваш) способ делает странные вещи на линии. http://snag.gy/dpXHr.jpg PsychoData 9 лет назад 0

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

2
Tyler

ERRORLEVEL не обновляет внутренние блоки управления, такие как операторы IF, если вы не используете! ERRORLEVEL! вместо% ERRORLEVEL% и используйте эту команду в начале вашего кода: setlocal ENABLEDELAYEDEXPANSION

см. http://batcheero.blogspot.ca/2007/06/how-to-enabledelayedexpansion.html

0
SadBunny

Ваша проблема в том, что вторая проверка выполняется в блоке кода, который используется ТОЛЬКО, если первая проверка равна 0. Вы похожи на:

IF (we want to go out) THEN ( IF (it rains) THEN ( take umbrella ) ) 

Смотрите, вторая проверка, чтобы увидеть, идет ли дождь, если, и ТОЛЬКО если, мы хотим выйти. Если мы не хотим выходить на улицу, мы не проверяем дождь.

Решение: закройте блок после первого IF, прежде чем перейти ко второму if, так что вы получите:

IF %ERRORLEVEL% EQU 0 ( do stuff ) IF %errorlevel% EQU 1 ( do other stuff ) 

Или используйте ELSE:

IF %ERRORLEVEL% EQU 0 ( do stuff ) ELSE ( :: errorlevel was anything other than 0, i.e. NEQ 0 do other stuff ) 
Итак, ваш ответ великолепен и все такое, но я думаю, что вы немного неправильно поняли. Я добавил psuedocode, чтобы объяснить мой общий мыслительный процесс без всего лишнего. В основном в Point2 я хочу выполнить команду DFC, а затем в Point3 мне нужно выполнить пару команд. Если он не заморожен, он пропустит этот IF и перейдет к P4. Здесь ничего не выполняется, и он завершит внутреннее IF и перейдет к P5. В P5 мы возвращаемся сразу после того, где мы оставили в первую очередь. PsychoData 9 лет назад 0
... Я вкладываю IFs неправильно или что-то? PsychoData 9 лет назад 0
Хм, кажется, я действительно не понял. Итак ... Ваша проблема в том, что строка "ECHO% errorlevel%" всегда возвращает 0 или всегда возвращает 1, даже если это не должно быть? Что это всегда возвращает? SadBunny 9 лет назад 0
Мой уровень ошибки всегда должен быть равен нулю, когда я вхожу в первый IF и достигаю точки 2, после этого dfc.exe будет выполняться и, если компьютер завис, уровень ошибки изменится на 1 (насколько я понимаю), но, несмотря ни на что, я никогда не вижу этого. Я даже пытался изменить строку, которая вызывает dfc get / ISFROZEN для вызова временного файла bat, который изменит уровень ошибки на что-то вроде 1231234, просто чтобы посмотреть, увижу ли я его. все еще не PsychoData 9 лет назад 0
0
wallyk

У меня нет машины с Windows, которая была бы легко доступна, но на моем месте я бы убедился, что ECHOутверждение не изменилось ERRORLEVEL.

Возможно, это не связано, но, возможно, вы используете интерпретатор команд, который по-разному обрабатывает прописные и строчные буквы ERRORLEVEL? Даже если это не имеет никакого эффекта, это свойственно быть непоследовательным.

Верхний / нижний регистр не имеет значения. Хотя это чище, я не буду редактировать это в вопросе, только мою копию. Я обычно заставляю все работать, а потом делаю это красиво. PsychoData 9 лет назад 0
Что касается эха, меняющего уровень ошибки, я думаю, что он останется таким, каким был раньше. Если вы говорите о строке, где я просто отображаю уровень ошибки, у меня была такая же проблема и раньше, и я просто вставил ее для устранения неполадок. http://stackoverflow.com/questions/20770788/why-the-return-value-of-echo-is-always-1 PsychoData 9 лет назад 0
Попробовал это; эхо не меняет уровень ошибки. SadBunny 9 лет назад 0
0
JonathanDavidArndt

Следующий пакетный файл даст вам статус, который вы ищете. Вы можете легко настроить gotosметки и в соответствии с вашими потребностями.

Существует ли файл, проверяется и ERRORLEVELобновляется соответствующим образом.

@echo off  REM --------------------------------------------------------------------------------- REM -- Check the status of Deep Freeze set "DFC=C:\Program Files (x86)\Faronics\Deep Freeze Enterprise\DFC.exe" if not exist "%DFC%" goto alwaysRun "%DFC%" get /ISFROZEN >nul 2>&1 if [9009] == [%ERRORLEVEL%] goto alwaysRun if ERRORLEVEL 1 goto isFrozen if ERRORLEVEL 0 goto isThawed REM ---------------------------------------------------------------------------------      REM --------------------------------------------------------------------------------- REM -- Run all the commands when the workstation is frozen REM -- (these commands are skipped when the workstation is thawed) goto alwaysRun :isFrozen  echo The workstation is frozen REM ---------------------------------------------------------------------------------      REM --------------------------------------------------------------------------------- REM -- Run all the commands when the workstation is thawed REM -- (these commands are skipped when the workstation is frozen) goto alwaysRun :isThawed  echo The workstation is thawed REM ---------------------------------------------------------------------------------      REM --------------------------------------------------------------------------------- :alwaysRun  echo Always run this part REM ---------------------------------------------------------------------------------      REM --------------------------------------------------------------------------------- :end pause