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

44

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

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

%JAVA_HOME%\bin;...

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

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

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

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

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

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

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

Ответы:

37

Ваш путь - это объединение системного пути и пользовательского пути. Кроме того, системные переменные среды могут не содержать ссылок на переменные среды пользователя, и любые такие ссылки не будут расширены. Чтобы получить желаемый результат, вставьте ссылку на% 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

по желанию.

JPaget
источник
3
В моей системе было несколько пользовательских переменных env с тем же именем, что и у некоторых системных переменных env. Повторение PATH не расширило бы их - после прочтения я удалил дубликаты пользовательских переменных, поскольку задавался вопросом, были ли они выбраны с приоритетом (но не могут быть расширены). Теперь это работает для меня - большое спасибо. :)
Майкл
Есть ли способ через Powershell получить оригинальный нерасширенный PATH? Я надеялся добавить к своему PATH, сохраняя в нем нерасширенные переменные среды.
CMCDragonkai
Решил это с некоторой помощью из другого вопроса. Напишите сценарий powershell, чтобы справиться с этим: gist.github.com/CMCDragonkai/a02d77c2d7c0799dd42fd2aab26a3cd5
CMCDragonkai
16

Проверьте в реестре Windows под этим ключом:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\Environment

ЕСЛИ переменная среды должна быть расширена (здесь:% JAVA_HOME%)

тогда переменная должна быть установлена ​​как значение REG_EXPAND_SZ .

При использовании reg.exe через командную строку для добавления / редактирования значений реестра по умолчанию введите REG_SZ. Укажите тип REG_EXPAND_SZ с помощью reg add /t REG_EXPAND_SZпараметра.

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

Существует определенная проблема с расширением переменных среды в переменной 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 подвергается некоторой дополнительной обработке в диалоговом окне Environment Variables, которая позволяет ему работать. Обработка не выполняется, когда переменная была добавлена ​​установщиком продукта (который, вероятно, просто изменил PATH в реестре напрямую).

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

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

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

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

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

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

RobDavenport
источник
7

Я спросил об этом на форумах 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

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

Sekhat
источник
2

Убедитесь, что в переменной PATH нет пробелов, когда вы определяете собственные переменные среды пользователя. например: C: \ GNAT \ bin; C: \ GNAT \ include не будет работать из-за пробела между ";" и "C: \ GNAT \ include".

Nij
источник
2

Добавьте переменные окружения во время входа в сеанс / console с помощью MSTSC.

Перезагрузите компьютер, и вы увидите, что переменные среды сохранятся.

Кажется, в O / S есть причуды в зависимости от того, как вы были подключены к машине, когда вы пытались изменить переменную среды.

Джастин
источник
1

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

из командной строки 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)

libjack
источник
1

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

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

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

BAP
источник
1

Я верю, что Windows не может раскрыть переменную в PATH, потому что она думает, что еще не определена. Рассмотреть возможность:

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

Эта гипотеза согласуется с моим другим наблюдением - добавление %ProgramFiles%\Somethingк пользователям PATH всегда приведет к ожидаемому расширению %ProgramFiles%, если оно было определено в машинной среде во время уведомления об изменении переменной (из-за порядка загрузки - MACHINE, а затем USER). Но когда вы модифицируете машинную среду, правильное расширение переменных происходит только во время загрузки (сейчас я понятия не имею, как и почему это не происходит на регулярной основе).

user539484
источник
1

Вы должны учитывать порядок, в котором переменные устанавливаются при входе в систему. Если вы попытаетесь использовать переменную до того, как она будет установлена, она появится как пустая строка.

Эффективный PATH - это конкатенация пользовательской переменной PATH, за которой следует глобальная переменная PATH.

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

(Это относится как минимум к Windows 7. Я не проверял это на более новых версиях.)

cbarrick
источник
0

Возможно, вы делаете это неправильно?

Я пробовал с Windows XP Pro SP3 (32 бита). У меня есть путь с несколькими вхождениями %JAVA_HOME%%JAVAFX_HOME%т. Д.). Я иду в командную строку, типа PATH, я вижу, переменные раскрыты. Хорошо.

Я изменяю значение JAVA_HOME. Вернуться к тому же окну командной строки, PATHснова то же значение ... как и ожидалось (по опыту!).

Я открываю новое окно командной строки, PATHнабираю, понял, я вижу новое значение.

Не уверен, каков точный механизм, но кажется, что любая запущенная программа, включая cmd.exe, захватывает значения переменных среды в момент запуска и не оглядывается назад ... (хотя я считаю, что программа с хорошим поведением может прислушайтесь к изменениям env, хотя и не уверен).

Это может быть замечено как особенность, ошибка или раздражение, но это так. По крайней мере, в отличие от Win9X, нам не нужно перезагружать компьютер! И в отличие от времени NT (IIRC), вам не нужно выходить из системы и обратно.

Почему несоответствие? Пути Microsoft непостижимы ... :-P

PhiLho
источник
Это не так После изменения мы тестируем в новом командном окне. Нам известно о том, что изменение системных значений не меняет значений для запущенных процессов.
skiphoppy
Хорошо, отсюда и «возможно» ... :-) И мое объяснение не охватывает несоответствия, но может быть полезно для некоторых новичков ...: -PI в основном хотел указать, что расширение переменных работает повсюду в пути. .. для некоторых систем! (все те, которые я использовал ... всегда 32-битные).
0

Я решил установить переменные среды в System> Advanced Settings> Environment Variables .

Есть две панели: переменные пользователя и глобальные (пользователь - ваше имя пользователя Windows) и системные переменные - глобальные переменные, поэтому, если вы установите «Новый» из переменных пользователя, например, JAVA_HOMEи укажите путь ниже, вы установите переменные, даже если ваш глобальный путь есть программные файлы в папке.

thunder_nemesis
источник