Вопрос или проблема
Я хочу запустить новый экземпляр программы или оболочки, такой как Far
(или cmd
), с некоторыми установленными переменными окружения. Я предпочитаю сделать для этого файл пакета. Я пробую следующее: в файле test.bat
я пишу:
set MYTESTVAR = MYTESTVAL
cmd
Когда я запускаю test.bat
, он открывает новую командную оболочку.
В этой новой оболочке я ввожу
set MYTESTVAR
Я ожидал бы увидеть
MYTESTVAR = MYTESTVAL
среди переменных, показанных в его выводе. Но вместо этого я вижу некоторые предопределенные переменные, те же, что я вижу в каждом новом экземпляре cmd
, запущенном непосредственно из Win-R, то же самое происходит, если я запускаю far.exe
вместо cmd
.
Таким образом, похоже, что когда Windows запускает новый процесс, он устанавливает всю окружение с нуля, вместо того чтобы наследовать его от родительского процесса. Это правда? как я могу запустить cmd
или far с установленными специфическими переменными, такими как MYTESTVAR
= MYTESTVAL
в моем примере выше?
Вероятно, PowerShell – это путь, но я бы предпочел что-то проще, такое как .bat
. Если ответ – PowerShell, я был бы признателен за пример скрипта для этого (я не очень знаком с PowerShell.).
Я на Windows 11, и в частности, я пытаюсь установить переменную:
set PerL5LIB = TESTPATH
И я ожидал, что когда я запущу 1perl
из такой оболочки, она увидит новую переменную, и она появится в ее @ENV
и @INC
. Но нет. Кажется, что новый процесс perl
не наследует окружение от оболочки. Это нормально?
Я думаю, что переменная PERL5LIB
была предназначена для использования, которое я пытаюсь. Эффект, похоже, не специфичен для Perl
, так как это происходит с cmd
и far
. Соответственно, я не упоминаю Perl
в заголовке и тегах.
Я подозреваю, что вопрос можно было бы сформулировать как эквивалент unix’овского export
в Windows.
из файла пакета, возможно ли установить переменные окружения для нового процесса? Т.е. запустить процесс с установленными специфическими переменными
Это возможно. Собственно в этом и заключается цель переменных окружения с самого начала.
Я протестировал ваш пример на Windows 11 24H2 и Windows XP SP3, и он работает на обеих системах.
Однако обратите внимание, что Cmd (как интерпретатор файла .bat) довольно чувствителен к местоположению пробелов, и в ваших примерах их нельзя добавлять как стилистический прием. Когда у вас есть пробелы вокруг =
, они буквально становятся частью имени переменной и значения; например, set PerL5LIB␣=␣TESTPATH
создает переменную с именем PerL5LIB␣
– с пробелом в конце его имени (и пробелом в начале его значения) – и ваш perl.exe его не распознает, потому что он ищет PERL5LIB
без пробелов.
(Возможно, Perl также чувствителен к регистру, как и в Linux, поэтому он может распознавать только PERL5LIB
, но не PerL5LIB
даже без добавленного пробела.)
Таким образом, похоже, что когда Windows запускает новый процесс, он устанавливает всю окружение с нуля, вместо того чтобы наследовать его от родительского процесса. Это правда?
Нет. Запускающий процесс может выбрать опцию указания пользовательского окружения для дочернего процесса (например, то, что делает Bash), но если бы то, что вы описали, было правдой для cmd
как родительского процесса, то переменные окружения не существовали бы как функция, поскольку они не смогли бы функционировать вообще.
- Some_Bat_001.cmd
@echo off
set "_Var_Value=AnyValue"
set "_SomeOtherValue=OtherExpectedValue"
setx _VarName %_Var_Value%
call Some_Bat_002.cmd
for /f usebackq^tokens^=3 %%i in =;(`
reg query "HKCU\Environment" /v _VarName 2^>nul
`);= do set "_ActualValue=%%~i"
if "%_Var_Value%" == "%_ActualValue%" =;(
echo/Still The Same! );= else if "%_ActualValu%" == "%_SomeOtherValue%" =;(
echo/New expected value has been assumed.);= else =;(
echo/The current value differs from the previous ones!
);=
- Some_Bat_002.cmd
@echo off
set "_ExpectedValue=SomeExpectedValue"
set "_SomeOtherValue=OtherExpectedValue"
if not defined _VarName for /f usebackq^tokens^=3 %%i in (`
reg query "HKCU\Environment" /v _VarName 2^>nul `);= do set "_VarName=%%~i"
if "%_VarName%" == "%_ExpectedValue%" =;(
echo/Still The Same! );= else if "%_VarName%" == "%_SomeOtherValue%" =;(
reg delete "HKCU\Environment" /v _VarName /f );= else =;(
setx _VarName SomeDiferrent_Value
);=
Если я правильно понимаю, вы можете использовать setx
для этих действий, где значение будет доступно в следующей сессии. Если нет, используйте reg query
в for /f
цикле, если необходимо и/или если вы хотите получить доступ к нему в той же сессии
Опционально, я предлагаю проверить этот ответ, но я не знаю автора.
Для обмена переменными между пакетными файлами вы можете попробовать:“Используйте setx для установки переменных окружения для будущих сессий, но если вам нужен немедленный доступ, используйте reg query в цикле.
Сохраните переменную в файле и прочитайте ее во втором пакете.
Передайте переменные в качестве аргументов, используя команды start или call.”
Некоторые дополнительные материалы для чтения:
При использовании команды cmd SET
, в 9,5 случаях из 10, по привычке используйте кавычки вокруг всего выражения, и по возможности избегайте использования внутри:
set "PerL5LIB=TESTPATH"
Вот несколько примеров того, как это работает с CMD /c
/k
& /r
, где /k
считается новой начальной дочерней сессией
.
Ответ или решение
Для решения поставленной задачи по созданию процесса с указанными переменными окружения из пакетного файла в Windows 11, рассмотрим теорию, приведем примеры конкретной реализации и объясним, как применять эти знания в вашем случае.
Теория
Переменные окружения в Windows используются для передачи информации о среде, в которой выполняется программа. Эти переменные могут быть временными, существующими только в рамках одной сессии, или постоянными, доступными в будущих сессиях. Когда вы создаете новый процесс с помощью командного интерпретатора cmd
, он наследует переменные окружения родительского процесса. Это позволяет вам задавать переменные окружения в родительской сессии и затем использовать их в дочернем процессе.
Команда set
используется для временного задания переменных окружения в текущей сессии, тогда как setx
сохраняет их для использования в будущих сессиях.
Пример
Ваша первоначальная попытка установить переменную в пакетном файле выглядит следующим образом:
set MYTESTVAR = MYTESTVAL
cmd
Однако из-за пробелов вокруг =
переменная MYTESTVAR
была задана некорректно. В Windows пробелы играют важную роль при задании переменных окружения. Корректный синтаксис будет следующим:
set "MYTESTVAR=MYTESTVAL"
cmd
Эта команда задает переменную без пробелов в её имени и значении, что делает её доступной в новой командной оболочке cmd
.
Кроме того, если вы хотите использовать setx
, чтобы сделать переменную доступной в дальнейших сессиях, вы можете использовать следующее:
setx MYTESTVAR MYTESTVAL
cmd
Применение
Для вашей цели, запустить процесс perl
с установленной переменной окружения, можно выполнить следующие шаги:
-
Создайте пакетный файл, к примеру
run_perl.bat
:@echo off set "PERL5LIB=TESTPATH" perl your_script.pl
-
Запустите созданный пакетный файл. Это создаст новый процесс, в котором переменная
PERL5LIB
будет доступна дляperl
.
Если вы предпочитаете PowerShell, то реализация будет выглядеть следующим образом:
$env:PERL5LIB = "TESTPATH"
Start-Process perl -ArgumentList "your_script.pl"
Возможные проблемы и решения
Обратите внимание, что если вы запускаете скрипты с помощью GUI-приложений или через ярлыки, установленные переменные окружения командной строки могут не учитываться. Во избежание этого запускайте приложения и скрипты из командной строки, где были установлены нужные переменные.
Если вы не уверены, что переменная установлена правильно, используйте команду set
(в cmd
) или Get-ChildItem Env:
(в PowerShell) для вывода всех переменных окружения и убедитесь, что ваша переменная списка.
Заключение
Установка переменных окружения из пакетного файла для нового процесса в Windows 11 является абсолютно возможной задачей, и вы можете использовать либо командную строку Windows, либо PowerShell, в зависимости от ваших предпочтений. Внимание к деталям, таким как корректная установка синтаксиса, и использование правильных инструментов (например, set
или setx
), позволит вам добиться нужного результата. Надеюсь, это руководство поможет вам уверенно работать с переменными окружения в вашей операционной системе.