Во-первых, прочитайте ответ на Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке? Объясняется, как правильно присвоить строковое значение средепеременная.Неверное значение set variable = value
, которое присваивает ПРОБЕЛ значение переменной среды с именем переменная ПРОБЕЛ , и по этой причине отсутствует переменная средыс именем переменная после этой командной строки.
Совершенно неверно, в большинстве случаев также set %variable%=value
, поскольку из-за этой командной строки значение присваивается переменной среды с именемопределяется значением переменной среды переменной .
Во-вторых, все ссылки на переменные среды выполняются с синтаксисом %variable%
в блоке команд, начинающемся с (
и заканчивающиеся соответствием )
расширяются на текущее значение переменной среды перед тем, как команда, использующая командный блок, будет выполнена вообще.Это означает, что все %variable%
заменены текущим значением указанной переменной среды, которое является ничем, если переменная с именем переменная еще не определена.
Давайте посмотрим, что на самом делевыполняется cmd.exe
для командного блока, например:
set "hostname02="
set "hostname1=0"
IF %hostname1% == 0 (
SET %hostname02% = 1
echo %hostname02% >> a.txt
PAUSE
)
Реально выполняемыми командными строками являются:
set "hostname02="
set "hostname1=0"
IF 0 == 0 (
SET = 1
echo 1>>a.txt
PAUSE
)
Результатом является завершение выполнения командного файла cmd.exe
с сообщением об ошибке:
Синтаксическая ошибка.
Это можно увидеть, запустив пакетный файл без @echo off
или с @echo ON
из окна командной строки.вместо двойного щелчка на командном файле.См. Также отладка пакетного файла .
Программист пакетного файла должен всегда учитывать, как командные строки действительно выполняются после обработки строк в пакетном сценарии, а некак они записаны в командном файле, особенно при использовании %variable%
, который динамически изменяет код во время выполнения скрипта.
Рабочий код для рассматриваемого примера кода:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist a.txt set /P hostname1=<a.txt
if not defined hostname1 set "hostname1=0"
echo hostname1 is: %hostname1%
if "%hostname1%" == "0" (
set hostname02=1
>>a.txt echo 1
) else if "%hostname1%" == "1" (
set hostname03=2
>>a.txt echo 2
goto EndBatch
) else if "%hostname1%" == "2" (
echo MSGBOX "Message">"%TEMP%\TEMPmessage.vbs"
%SystemRoot%\System32\wscript.exe "%TEMP%\TEMPmessage.vbs"
del "%TEMP%\TEMPmessage.vbs"
)
:EndBatch
endlocal
pause
Этот пакетный файл сначала устанавливает локальную среду с включенными расширениями команд, как требуется здесь, и отложенным расширением переменных среды, отключенным, как не требуется приведенным ниже кодом.Параметры EnableExtensions DisableDelayedExpansion
при использовании команды setlocal
могут быть опущены, поскольку расширения команд включены по умолчанию и отложенное расширение по умолчанию отключено при запуске нового командного процесса, как это делается при двойном щелчке по пакетному файлу.Но всегда желательно явно определить среду, необходимую для пакетного файла.Прочитайте этот ответ для получения подробной информации о командах SETLOCAL и ENDLOCAL .
Следующая строка назначает первую строку файла a.txt
переменной средыhostname1
если этот файл вообще существует в текущем каталоге, что, конечно, может отличаться от каталога пакетного файла, в зависимости от того, как пакетный файл был запущен для выполнения с помощью cmd.exe
.
Команда FOR с параметром /F
обычно используется для построчного чтения текстового файла и назначения строк, считанных из файла, переменным среды.Но set /P variable=<file.txt
также можно использовать для назначения первой строки file.xt
переменной окружения variable
.
Четвертая командная строка проверяет, определена ли теперь переменная hostname1
, что не так, еслифайл a.txt
не существует в текущем каталоге или этот файл начинается с пустой строки.Переменная среды hostname1
определяется со значением 0
, если она не определена после третьей строки.
Далее для визуальной проверки выводится текущее значение переменной hostname1
.
Затем три IF условия используются для сравнения строк с учетом регистра.Строки для сравнения заключены в двойные кавычки, что делает пакетный файл более отказоустойчивым против выхода из-за синтаксической ошибки в зависимости от строки, прочитанной из файла a.txt
.Но это решение все еще не на 100% отказоустойчиво, см. Ответ на Как остановить интерпретатор команд Windows от завершения выполнения пакетного файла при неправильном вводе пользователем? для получения подробной информации о том, как получить код отказоустойчивого пакетного файла наиспользование set /P
со строковым значением, введенным пользователем или считанным из файла, который каждый пользователь может редактировать перед запуском пакетного файла.
Строковые значения, присвоенные hostname02
и hostname03
, фиксируются в кодеи, следовательно, эти строковые значения могут быть непосредственно записаны также в файл a.txt
без необходимости ссылаться на переменные окружения hostname02
и hostname03
, определенные внутри командных блоков, что потребовало бы отложенного расширения переменной окружения.
оператор перенаправления >>
и имя файла записываются в начале строки для реальной записи в файл a.txt
просто 1
или 2
без завершающего пробела, если на этих двух echo
нет завершающих пробеловкомандные строки в командном файле.При использовании echo 1 >>a.txt
пробел между 1
и >>
также будет записан в файл a.txt
.И echo 1>>a.txt
вообще не будет записывать 1
в файл a.txt
.Подробнее читайте в статье Microsoft о Использование операторов перенаправления команд .Командный процессор Windows переформатирует >>a.txt echo 1
в echo 1 1>>a.txt
перед выполнением этой командной строки.Так >>a.txt
в начале строки после пробелов отступа для лучшей читабельности перемещается интерпретатором команд Windows при разборе в конец командной строки с добавлением 1
(пробел и один) слева для перенаправленияoperator >>
.
VBScript выполняется либо с cscript.exe
- консольной версией хоста скриптинга Windows - либо с wscript.exe
- GUI версией хоста скриптинга Windows.Команда CALL не подходит для выполнения сценария VBScript.Таким образом, пакетный файл использует wscript.exe
для запуска сценария VBScript с простым окном сообщения.
Чтобы понять используемые команды и их работу, откройте окно командной строки, выполните следующие команды и полностью прочитайтевсе страницы справки отображаются для каждой команды очень тщательно.
del /?
echo /?
endlocal /?
goto /?
if /?
pause /?
set /?
setlocal /?
wscript /?