Почему Windows не может обрабатывать переменную среды в Path?

67286
skiphoppy

У меня и моего коллеги одинаковые рабочие станции Dell с установленной Windows XP Professional x64 edition.

Моя переменная окружения Path начинается с:

%JAVA_HOME%\bin;... 

Переменная Path моего коллеги включает в себя тот же каталог, указанный с использованием той же переменной окружения, но это не первый элемент в его Path.

Если я обращаюсь к системным свойствам -> переменным окружения и изменяю значение моей переменной JAVA_HOME, версия java, найденная из командной строки, изменяется, как я ожидаю. Это запускает совершенно новое окно консоли, чтобы быть уверенным, что вы подберете изменения.

Но на машине моего коллеги это не так. Он продолжает находить свою предыдущую версию Java, пока не вызовет переменную Path и не сохранит ее (даже если он не вносит в нее изменений). (Опять же, это при запуске совершенно нового окна консоли.)

Я наблюдаю это несоответствие в Windows в течение приблизительно 6 месяцев и очень любопытно об этом. У нас в офисе слишком много версий Windows, поэтому до сих пор у меня не было возможности увидеть, как это происходит на двух машинах с одинаковой версией ОС.

Чем это вызвано? Почему его машина не переоценивает Path, используя новый JAVA_HOME, когда мой делает?

(Это потому, что это не первое, что есть на Пути? Если да, то как это может быть и почему? Я бы сделал больше тестов, чтобы проверить, но я думаю, что теперь он сыт этим по горло и хотел бы вернуться к работе. .)

38
Для всех вас, парни, голосующих за закрытие (3 на данный момент) ... если где-то есть дуп, комментарий, указывающий на это, наверняка был бы хорош. Если это не обман ... тогда было бы неплохо сказать, что вы думаете не так с этим вопросом. skiphoppy 15 лет назад 6
Возможно, потому что это скорее системный вопрос, чем программный, хотя он имеет прямое влияние на программирование, поэтому я не голосую за его закрытие ... :) 15 лет назад 1
Вниманию нацистов: Я хотел бы поддержать мнение о том, что если вопрос был уместен в отношении переполнения стека до того, как появились superuser.com и serverfault.com, то он все еще актуален сегодня. Это вопрос программирования. skiphoppy 15 лет назад 6
Вы имеете в виду, что программисты - только пользователи Windows, у кого может быть эта проблема? Заткнись, программист-нацист! Во-вторых, до того, как появился более подходящий сайт вопросов и ответов, у вас не было возможности разместить вопрос здесь. Гостеприимство SO не должно быть аргументом для злоупотребления им. Val 11 лет назад 0
Я смотрю на это в Windows 10 - подстановка переменных в PATH не работает _ периодически Переход к переменным среды и сохранение (без изменений), а затем открытие нового приглашения CMD решило проблему. Thomas W 8 лет назад 0

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

34
JPaget

Ваш путь - это объединение системного пути и пользовательского пути. Кроме того, системные переменные среды могут не содержать ссылок на пользовательские переменные среды, и любые такие ссылки не будут расширены. Чтобы получить желаемый результат, вставьте ссылку на% JAVA_HOME% в пользовательскую переменную среды PATH или создайте такую ​​переменную, если она еще не существует.

Возможно, упрощенный пример прояснит это. Предположим, что среда SYSTEM

ProgramFiles = C:\Program Files SystemRoot = C:\WINDOWS PATH = %SystemRoot%\SYSTEM32 

и среда пользователя JSmith является

JAVA_HOME = %ProgramFiles%\Java\bin USERPROFILE = C:\USERS\JSmith PATH = %JAVA_HOME%\bin;%USERPROFILE%\bin 

тогда результирующий путь будет

C:\WINDOWS\SYSTEM32;C:\Program Files\Java\bin;C:\Users\JSmith\bin 

по желанию.

В моей системе было несколько пользовательских переменных env с тем же именем, что и у некоторых системных переменных env. Повторение PATH не расширило бы их - после прочтения я удалил дубликаты пользовательских переменных, так как подумал, были ли они выбраны с приоритетом (но не могут быть расширены). Теперь это работает для меня - большое спасибо. :) Michael 10 лет назад 2
Есть ли способ через Powershell получить оригинальный нерасширенный PATH? Я надеялся добавить к своему PATH, сохраняя в нем нерасширенные переменные окружения. CMCDragonkai 7 лет назад 0
Решил это с некоторой помощью из другого вопроса. Напишите сценарий PowerShell для этого: https://gist.github.com/CMCDragonkai/a02d77c2d7c0799dd42fd2aab26a3cd5 CMCDragonkai 7 лет назад 0
13
climenole

Check in the Windows registry under this key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\Environment 

IF the environment variable needs to be expanded (here: %JAVA_HOME%)

then the variable must be set as a REG_EXPAND_SZ value.

If using reg.exe via command-line to add/edit registry values, it defaults to type REG_SZ. Specify the type REG_EXPAND_SZ by using the reg add /t REG_EXPAND_SZ option.

да ... это одна из тех настроек, которые я всегда забываю ... надоедливый реестр ;-) Eddie B 11 лет назад 0
9
RobDavenport

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

Мы создали наши собственные переменные системного уровня, такие как «OUR_ROOT = c: \ MyRoot», а затем использовали их в системном PATH, например «PATH =;% OUR_ROOT% \ bin;» и это правильно раскрывается в "PATH =; c: \ MyRoot \ bin;". Пока проблем нет.

Но в Windows 7 (32-разрядная версия) я сам установил продукт и создал системные переменные среды, например:

STUDIO_BIN=C:\program files\Company Name\Product Name 10.4\bin 

и он добавил его в системную переменную PATH:

PATH=<other path elements>;%STUDIO_BIN%;<more path elements> 

Но значения PATH, показанные в CMD, содержали «% STUDIO_BIN%;» а не расширенный путь. Значение в «Мой компьютер»> «Свойства»> «Дополнительно»> «Env.Vars» также не изменилось. Это означало, что я не мог запускать программы, которым требовалась DLL в этом каталоге.

Просто изменив STUDIO_BIN (через Мой компьютер> Свойства> Дополнительно ...> Env Vars) на имя без встроенных пробелов:

STUDIO_BIN=C:\ProductName\bin 

и затем перезапуская окно CMD, PATH теперь:

PATH=<other path elements>;C:\ProductName\bin;<more path elements> 

Другое решение состоит в том, чтобы в достаточной степени отредактировать системную переменную, которую вы используете в PATH, с помощью диалогового окна «Мой компьютер»> «Свойства»> «Дополнительно»> «Переменные среды». Я попытался добавить символ и удалить его, чтобы внести «изменения», а затем «ОК» вышел, запустил новое приглашение CMD, и PATH НЕ был правильно расширен. Затем я попытался удалить часть пути, чтобы это было

STUDIO_BIN=C:\Program Files\Company Name 

(опуская "Название продукта 10.4") и вот, и следующее приглашение CMD показало PATH с правильно расширенным STUDIO_BIN!

Как ни странно, если я вернулся и добавил «Имя продукта 10.4» в STUDIO_BIN (включая все пробелы, которые были изначально там до того, как я начал работать с ним), и PATH все равно был правильно расширен.

Очевидно, что при достаточном изменении содержимого переменная PATH подвергается некоторой дополнительной обработке в диалоговом окне «Переменные среды», которая позволяет ему работать. Обработка не выполняется, когда переменная была добавлена ​​установщиком продукта (который, вероятно, просто изменил PATH в реестре напрямую).

Я почти уверен, что это была проблема и с XP. Он только что появился у меня в Windows 7, когда я собирал новую машину для разработки. Видимо, это не было исправлено Microsoft.

Очевидно, что даже переменные, определенные в MS, такие как% ProgramFiles%, не будут правильно расширяться в переменной PATH.

Эта страница дает возможный ответ, если вы устанавливаете PATH через командную строку или командный файл. (Заключите всю команду после SET в кавычки.) Я не знаю, какой установщик установил продукт, который я установил, для установки переменных среды, но он явно обходил любую обработку, необходимую для правильного расширения путей пробелами.

Итак, подведем итог: вы можете:

  • изменить пути (и переместить все связанные файлы) на пути без пробелов, или

  • отредактируйте переменные, которые не могут быть расширены, в диалоговом окне «Переменные среды» (изменив их достаточно для правильной обработки - я не уверен, насколько этого достаточно).

7
Ian Boyd

Я спросил об этом на форумах Microsoft в марте 2009 года, но так и не решил:

Как использовать% ProgramFiles% в переменной среды Path? :


Я пытаюсь добавить папку в системную переменную окружения Path.

я хочу добавить % ProgramFiles% \ SysInternals

к существующей переменной пути:

C: \ PROGRA ~ 1 \ Borland \ Delphi5 \ Projects \ BPL; C: \ PROGRA ~ 1 \ Borland \ Delphi5 \ Bin; % SystemRoot% \ system32; % SystemRoot% ;% SystemRoot % \ System32 \ Wbem; C: \ Program Files \ Microsoft SQL Server \ 80 \ Tools \ BINN; C: \ Program Files \ Microsoft SQL Server \ 80 \ Tools \ Binn \; C: \ Program Files \ Microsoft SQL Server \ 90 \ Tools \ binn \; C: \ Program Files \ Microsoft SQL Server \ 90 \ DTS \ Binn \; C: \ Program Files \ Microsoft SQL Server \ 90 \ Tools \ Binn \ VSShell \ Common7 \ IDE \; C: \ Program Files \ Microsoft Visual Studio 8 \ Common7 \ IDE \ PrivateAssemblies \;% SYSTEMROOT % \ System32 \ WindowsPowerShell \ v1.0 \

Так что я иду в место, где вы редактируете это:

альтернативный текст

И я добавляю свою переменную в путь:

% ProgramFiles % \ SysInternals; C: \ PROGRA ~ 1 \ Borland \ Delphi5 \ Projects \ Bpl; (надрез)

Затем, открыв новое окно командной строки, переменная среды не заменяется ее фактическим значением:

Путь =% ProgramFiles % \ SysInternals; C: \ PROGRA ~ 1 \ Borland \ Delphi5 \ Projects \ Bpl (snip)>

Который вы можете увидеть на следующем скриншоте:

альтернативный текст


Но чтобы ответить на ваш вопрос: я не знаю. Похоже, это не может быть сделано.

5
Sekhat

Существует два уровня переменных среды: глобальный и пользовательский. Если он установил% Java_home% в качестве переменной окружения пользователя, но вместо этого изменил глобальную переменную, он не увидит никакой разницы.

2
Nij

Make sure there are no spaces in the PATH when you are defining your own user environment variables. eg: C:\GNAT\bin; C:\GNAT\include wont work, because of the space between the ";" and "C:\GNAT\include".

2
Justin

Add the environment variables whilst logged onto the /console session using MSTSC.

Reboot the machine and you will find your environment variables will have persisted.

There appears to be a quirk in the O/S depending on how you were connected to the machine when you attempted to change the environment variable.

1
libjack

Это может быть связано с функцией «отложенного расширения переменной среды» (или ее отсутствием), или, возможно, вы можете воспользоваться этой функцией, чтобы всегда иметь правильное решение.

из командной строки cmd

set /? 

и прочитайте раздел, описывающий «отложенное расширение переменной среды», который включает небольшой пример для тестирования

set VAR=before if "%VAR%" == "before" ( set VAR=after if "%VAR%" == "after" @echo If you see this, it worked ) 

Если вы не получите линию эха, то это может объяснить это ...

Однако, если вы запускаете cmd.exe с параметром / V, вы можете использовать "!" вместо "%", который меняет поведение

set VAR=before if "%VAR%" == "before" ( set VAR=after if "!VAR!" == "after" @echo If you see this, it worked ) 

У меня (работает на XP) 1-й скрипт не работал, но вторая версия работала (с cmd.exe / V)

1
BAP

У меня была такая же проблема, и я знаю, как ее исправить, она хромая.

Просто измените ваш PATH еще раз, но не вносите изменений, и заново сохраните PATH. По какой-то причине это приводит к повторной оценке всех вложенных ссылок на переменные среды.

Если это не работает, сделайте это еще несколько раз, так или иначе это просто работает само по себе.

1
user539484

I do believe what Windows fails to expand a variable in PATH because it thinks what it not defined yet. Consider:

REM Ensure variable is undefined SET UNDEFINED= REM And then try to expand it ECHO UNDEFINED=%UNDEFINED% 

This hypothesis conforms with my other observation - adding %ProgramFiles%\Something to the users PATH will always result in expected expansion of %ProgramFiles%, given it has been defined in machine environment at the time of variable change notification (due loading order - MACHINE and then USER). But when you modify machine environment correct variable expansion only happens at the boot time (right now I have no idea how and why this not happens on the regular basis).