Этот пакетный скрипт завершается, когда %CHECKCONTINUE%
получает нулевое значение, не вводя ничего в строке 13 ( SET /p CHECKCONTINUE=Okay to continue? (y/n):
), почему это?
@ECHO OFF
SETLOCAL
TITLE Registry restore script
REM Restores registry settings and disables the cloud
SET %CHECKCONTINUE%=
:listaction
ECHO I'm about to...
ECHO 1.) Remove the registry data that specifies settings for TF2
ECHO 2.) Forcibly disable Steam Cloud.
ECHO.
SET /p CHECKCONTINUE=Okay to continue? (y/n):
REM No?
IF %CHECKCONTINUE%==n GOTO exit
IF %CHECKCONTINUE%==no GOTO exit
REM Yes?
IF %CHECKCONTINUE%==y GOTO start
IF %CHECKCONTINUE%==yes GOTO start
REM Did they put something else?
IF DEFINED %CHECKCONTINUE% GOTO loop-notvalid
REM Did they not put anything at all?
IF NOT DEFINED %CHECKCONTINUE% GOTO loop-noreply
:start
REM Delete application specific data
REG DELETE HKEY_CURRENT_USER\Software\Valve\Source\tf\Settings /f
REG DELETE HKEY_CURRENT_USER\Software\Valve\Steam\Apps\440 /f
REM Disable Steam Cloud for TF2
REG ADD HKEY_CURRENT_USER\Software\Valve\Steam\Apps\440 /v Cloud /t REG_DWORD /d "0x0" /f
:exit
ENDLOCAL
EXIT
:loop-notvalid
ECHO.
ECHO That's not a valid reply. Try again.
ECHO.
SET %CHECKCONTINUE%=
GOTO listaction
:loop-noreply
ECHO.
ECHO You must enter a reply.
ECHO.
SET %CHECKCONTINUE%=
GOTO listaction
Ответы:
Во-первых, на нескольких строках у вас есть:
Это не меняет
CHECKCONTINUE
но использует его значение в качестве имени переменной.Измените это на:
Также было бы лучше, если бы вы переместили его сразу выше
set /p ...
- таким образом, вам понадобится только один раз.if defined
также принимает только имя переменной, поэтому вместовы должны использовать:
То же относится и к этой строке:
Однако его можно сократить до:
Если переменная была определена, выполнение так или иначе никогда не достигнет этой строки (
if defined ...
выше)Вот как бы я написал это:
источник
exit
будет завершать оболочку тоже, а не только сценарий. В скрипте следует использовать либоgoto :EOF
или жеexit /b
, (endlocal
не обязательно.)set /p check=Okay to continue? (y/n)
:(if not defined check goto :loop-noreply
,if not defined check goto :loop-noreply
как проверка, это заканчивается ...:loop-noreply
раздел? Кроме того, попробуйте переместитьnot defined
проверьте сразу послеset /p
, И запустить все из окна командной строки, сообщения об ошибках являются полезно.Разъяснение великого ответа Гравити:
Сначала ответим на ваш вопрос: Почему пакетный скрипт завершается, когда% CHECKCONTINUE% получает нулевое значение?
Проблема в строке 16, вы делаете это:
поскольку
CHECKCONTINUE
имеет значение "undefined", оно оценивается как "пустая" строка, поэтому оператор в строке 16 фактически выполняетЭто неверное утверждение, потому что в левой части
"=="
, Итак, пакетный скрипт завершается, когда он пытается выполнить неправильно отформатированный оператор:У вас будет похожая проблема, если кто-то напечатает что-то, в котором есть пробел:
Чтобы это исправить, вы должны использовать двойные кавычки вокруг таких слов:
Это необходимо, если используемые переменные могут быть «пустыми» или иметь встроенные пробелы, но это просто хорошая идея всегда использовать двойные кавычки при оценке с
"=="
,Примечание. Некоторые ошибки (например, приведенная выше с
"if"
а также"=="
являются «фатальными» ошибками, которые приведут к немедленному прекращению выполнения пакетного скрипта. Другие ошибки (как показано ниже с"set"
), являются «несмертельными» ошибками. Для «нефатальных» ошибок оператор с ошибкой НЕ выполняется, отображается сообщение об ошибке, и пакетный сценарий продолжает выполняться, начиная со следующего оператораДалее, как Grawity указал об этой строке:
Это не изменяет CHECKCONTINUE, но использует его значение в качестве имени переменной.
Опять же, если
CHECKCONTINUE
был "неопределен", он будет оцениваться как "пустая" строка, поэтому оператор фактически делает:Это также неверное утверждение, потому что в левой части
"="
,И эти строки:
"if defined"
(а также"if not defined"
) ожидает имя переменной, а не значение переменной. ЕслиCHECKCONTINUE
был неопределен,%CHECKCONTINUE%
будет вычислять пустую строку, и эти операторы будут:Вот,
"if defined"
(а также"if not defined"
) собирается проверить, если переменная с именемGOTO
определяется или нет.Кроме того, для этих 3 строк, если
CHECKCONTINUE
был на самом деле определен,"set"
а также"if defined"
будет работать на"value"
переменной, а не"name"
самой переменной. Так что еслиCHECKCONTINUE
уже имел значение"y"
, затем:будет выглядеть так:
Пример "script.cmd":
Запустив "script.cmd", вы получите:
Кроме того, в качестве альтернативы
"set /p"
, вы могли бы использовать"choice"
:Примечание: код на этикетке:
"loop-notvalid"
не является необходимым, потому что «выбор» не будет принимать неопределенные ответы (да / нет).Кроме того, единственный способ получить «пустой» ответ от «выбора» - это если пользователь нажимает «Ctrl-C» для завершения пакетного задания, а затем вводит N (Нет) в «Завершить пакетное задание» (Y / N)?» подсказка, указывающая, что они НЕ хотят выходить. Приведенный выше код ловит это и печатает сообщение, затем переходит (переход) к метке «: listaction», чтобы повторно запросить пользователя, поэтому вам также не нужен код с меткой «loop-noreply».
Нет необходимости «сбрасывать» уровень ошибки, поскольку команда выбора позаботится об этом. И нет необходимости очищать
CHECKCONTINUE
переменная, потому что она всегда установлена равной%errorlevel%
до значенияCHECKCONTINUE
рассматриваетсяПо умолчанию выбор «нечувствителен к регистру», поэтому нажатие «Y» или «N» аналогично нажатию «y» или «n». Это поведение можно изменить, указав
/cs
на выбор командной строки.источник