Я пытаюсь передать переменную среды в Node.js с помощью PowerShell следующим образом:
Ответ 3
Note: If you can assume that Node.js is already installed - as is by definition the case when you're invoking [TG40] - consider use of [TG41] helper packages, as shown in Cyril CHAPON helpful answer.
This answer focuses on generic solutions from within PowerShell.
ТЛ; др
# Set env. variable temporarily, invoke the external utility, remove / restore old value.
$oldVal, $env:MYVAR = $env:MYVAR, 8000; node index.js; $env:MYVAR = $oldVal
# More structured alternative that uses a local variable.
& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }
Проще говоря, если нет ранее существовавшего значения MY_VAR
, которое необходимо восстановить.
$env:MYVAR=8000; node index.js; $env:MYVAR=$null
# More structured alternative
& { $env:MY_VAR=8000; node index.js; $env:MY_VAR=$null }
См. ниже объяснение и альтернативу на основе вспомогательной функции.
В дополнение к эффективному ответу Харикришнана:
PowerShell не имеет эквивалента для метода передачи команд среды передачи, который предлагает POSIX-подобная оболочка (начиная с PowerShell v7 - однако его введение в PowerShell - не обязательно с тем же синтаксисом) обсуждается в это проблема GitHub); например.:
# E.g., in *Bash*:
# Define environment variable MY_VAR for the child process being invoked ('node')
# ONLY; in other words: MY_VAR is scoped to the command being invoked
# (subsequent commands do not see it).
MY_VAR=8000 node index.js
В PowerShell, как показывает ответ харикришнана, сначала нужно определить переменную среды, а затем в отдельном выражении вызвать внешнюю программу, поэтому $env:MY_VAR="8000"; node index.js
является правильным решением PowerShell, но ничего не стоит, чтобы $env:MY_VAR
оставалось в области для оставшейся части сеанса (это установлено на уровне процесса).
Обратите внимание, что даже использование блока сценария, вызванного с помощью &
для создания дочерней области, здесь не помогает, поскольку такие дочерние области применяются только к переменным PowerShell, а не к переменным среды.
Конечно, вы можете удалить переменную среды вручную после вызова node
:
Remove-Item env:MY_VAR
или даже просто $env:MY_VAR = $null
, это то, что показывает 1-я команда сверху.
Более структурированная альтернатива - возможно, лучше в случае установки нескольких переменных среды и/или вызова нескольких команд - заключается в использовании блока сценария, вызываемого с помощью &
:
& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }
Это использует преимущества:
{ ... }
- блок сценариев, который обеспечивает четко видимую группировку для команд в нем; вызывается с помощью &
, создает локальную область видимости, поэтому вспомогательная переменная $oldVal
автоматически выходит из области действия при выходе из блока.
$oldVal, $env:MY_VAR = $env:MY_VAR, 8000
сохраняет старое значение (если оно есть) из $env:MY_VAR
в $oldVal
при изменении значения на 8000
; Этот метод одновременного присваивания нескольким переменным (в некоторых языках называется деструктурирующим присваиванием) объясняется в Get-Help about_Assignment_Operators
, раздел "НАЗНАЧЕНИЕ НЕСКОЛЬКИХ ПЕРЕМЕННЫХ".
В качестве альтернативы, используйте вспомогательную функцию , описанную ниже, или используйте подход try { ... } finally { ... }
, как показано в этом связанном ответе моего.
Вспомогательная функция для изменения среды в области команд.
Если вы определили вспомогательную функцию ниже (помните, что определения функций должны быть помещены до их вызова), вы можете добиться изменения среды в командной строке следующим образом:
# Invoke 'node index.js' with a *temporarily* set MY_VAR environment variable.
Invoke-WithEnvironment @{ MY_VAR = 8000 } { node index.js }
Invoke-WithEnvironment()
исходный код:
function Invoke-WithEnvironment {
<#
.SYNOPSIS
Invokes commands with a temporarily modified environment.
.DESCRIPTION
Modifies environment variables temporarily based on a hashtable of values,
invokes the specified script block, then restores the previous environment.
.PARAMETER Environment
A hashtable that defines the temporary environment-variable values.
Assign $null to (temporarily) remove an environment variable that is
currently set.
.PARAMETER ScriptBlock
The command(s) to execute with the temporarily modified environment.
.EXAMPLE
> Invoke-WithEnvironment @{ PORT=8080 } { node index.js }
Runs node with environment variable PORT temporarily set to 8080, with its
previous value, if any
#>
param(
[Parameter(Mandatory)] [System.Collections.IDictionary] $Environment,
[Parameter(Mandatory)] [scriptblock] $ScriptBlock
)
# Modify the environment based on the hashtable and save the original
# one for later restoration.
$htOrgEnv = @{}
foreach ($kv in $Environment.GetEnumerator()) {
$htOrgEnv[$kv.Key] = (Get-Item -EA SilentlyContinue "env:$($kv.Key)").Value
Set-Item "env:$($kv.Key)" $kv.Value
}
# Invoke the script block
try {
& $ScriptBlock
} finally {
# Restore the original environment.
foreach ($kv in $Environment.GetEnumerator()) {
# Note: setting an environment var. to $null or '' *removes* it.
Set-Item "env:$($kv.Key)" $htOrgEnv[$kv.Key]
}
}
}