Сначала я рекомендую открыть окно командной строки и запустить setlocal /?
и endlocal /?
, чтобы отобразить справку / документацию для этих двух команд. Очень важно знать, что каждый setlocal
без соответствующего endlocal
приводит к неявному выполнению endlocal
на cmd.exe
перед выходом из обработки пакетного файла или подпрограммы, вызываемой с помощью команды CALL .
Далее я предлагаю прочитать этот ответ для получения более подробной информации о командах SETLOCAL и ENDLOCAL и о том, что происходит при их использовании.
Я предлагаю, например, michael_heath , чтобы изменить этот блок кода:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
set CLASSPATH=!CLASSPATH!
Лучше было бы:
setLocal EnableExtensions EnableDelayedExpansion
set CLASSPATH=.
for /R "%JRE_HOME%\lib" %%a in (*.jar) do set "CLASSPATH=!CLASSPATH!;%%a"
endlocal & set "CLASSPATH=%CLASSPATH%"
Теперь локальная среда заканчивается передачей переменной среды CLASSPATH
из локальной среды, в которой она была определена, в восстановленную предыдущую среду, поскольку cmd.exe
расширяет %CLASSPATH%
до текущего значения переменной среды CLASSPATH
в текущей локальной среде перед выполнением команды endlocal
, которая восстанавливает предыдущую среду.
Неправильно в вашем пакетном файле также set WINDIR=%SystemRoot%;%SystemRoot%
, который должен быть set "WINDIR=%SystemRoot%"
.
Рекомендую к прочтению Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке? Это объясняет, почему в наше время рекомендуется синтаксис set "variable=string value"
. Во многих определениях переменных среды прямо или косвенно используется %UserProfile%
, что означает, что в зависимости от того, что пользователь, в данный момент использующий пакетный файл, ввел в качестве имени пользователя при создании учетной записи пользователя. Я видел пользователей, которые вводили свои имена, содержащие пробел и символы, не входящие в ASCII. И я видел пользователей, создающих учетную запись с именем пользователя, содержащим символ &
, например Company GmbH & Co
. Амперсанд вне строки аргумента в двойных кавычках интерпретируется как оператор AND и cmd.exe
пытается выполнить после set
также оставшуюся строку после &
как командную строку, используя что-то вроде set USERHOME=%DEVHOME%\%USERNAME%
вместо set "USERHOME=%DEVHOME%\%USERNAME%"
. Ну, startdev.bat
переопределяет почти все предопределенные переменные среды Windows , включая USERNAME
и USERPROFILE
, и поэтому написано безопасно для большинства определений переменных среды.
Этот блок кода также не оптимален:
FOR /F "usebackq" %%i IN (`hostname`) DO SET HOSTNAME=%%i
echo Running on hostname: %HOSTNAME%
Имя хоста, соответственно имя компьютера, может также содержать пробел или символы, важные для командной строки, или начинаться с точки с запятой по неизвестной причине. Так что лучше бы:
FOR /F delims^=^ eol^= %%i IN ('hostname') DO SET "HOSTNAME=%%i"
setlocal EnableDelayedExpansion & echo Running on host name: !HOSTNAME!& endlocal
При этом существует переменная окружения COMPUTERNAME
, предопределенная Windows, позволяющая использовать только следующую командную строку:
setlocal EnableDelayedExpansion & echo Running on host name: !ComputerName!& endlocal
Командная строка ECHO , содержащая немедленно развернутую ссылку на переменную среды, для которой неизвестно, если ее значение содержит &|<>
, всегда является проблемой, поскольку ссылка на переменную среды раскрывается до дальнейшей обработки команды строка cmd.exe
, как описано в Как интерпретатор сценариев команд Windows (CMD.EXE) анализирует сценарии?
Предлагаю также прочитать тему форума DosTips ЭХО. Не удается дать текст или пустую строку. Вместо этого используйте ECHO / и избегайте использования echo.
в командном файле для вывода пустой строки.