Pass Node.js environment variable with Windows PowerShell
Set environmental variable MY_VAR
first and run your app like this:
C:\Users\everton\my-project> $env:MY_VAR="8000" ; node index.js
You can access environmental variable MY_VAR
inside index.js
by
process.env.MY_VAR
Note: PowerShell doesn't directly support command-scoped environment variables. The above command sets the environment variable for that PowerShell session.
My answer require the use of Node.js and npm libraries.
...or you just take out the pain of writing obscure-WTF-language-scripting, and use one of command-scoped (plus cross-platform) Node.js scripts:
cross-env
(for inline)cross-env MYVAR=MYVALUE node index.js
env-cmd
(from .env file)env-cmd .env node index.js
with
#.env file MYVAR=MYVALUE
Note: If you can assume that Node.js is already installed - as is by definition the case when you're invoking node
- consider use of npm
helper packages, as shown in Cyril CHAPON 's helpful answer.
This answer focuses on generic solutions from within PowerShell.
tl;dr
# Set env. variable temporarily, invoke the external utility,
# then remove / restore old value.
$oldVal, $env:MYVAR = $env:MYVAR, 8000; node index.js; $env:MYVAR = $oldVal
# Scoped alternative that uses a *transient* helper variable.
& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }
More simply, if there's no preexisting MY_VAR
value that must be restored.
$env:MYVAR=8000; node index.js; $env:MYVAR=$null
See below for an explanation and an alternative based on a helper function.
To complement Harikrishnan's effective answer:
PowerShell has no equivalent to the command-scoped method of passing environment variables that POSIX-like shells offer (as of PowerShell v7 - however, introducing it to PowerShell - not necessarily with the same syntax - is being discussed in GitHub issue #3316); e.g.:
# 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
In PowerShell, as Harikrishnan's answer demonstrates, you have to define the environment variable first, and then, in a separate statement, call the external program, so $env:MY_VAR="8000"; node index.js
is the right PowerShell solution, but it is worth nothing that $env:MY_VAR
stays in scope for the remainder of the session (it is set at the process level).
Note that even using a script block invoked with &
to create a child scope doesn't help here, because such child scopes only apply to PowerShell variables, not environment variables.
You can, of course, remove the environment variable manually after the node
call:Remove-Item env:MY_VAR
or even just $env:MY_VAR = $null
, which is what the 1st command at the top shows.
A more structured alternative - perhaps better in the case of setting multiple environment variables and/or invoking multiple commands - is to use a script block invoked with &
:
& { $oldVal, $env:MY_VAR = $env:MY_VAR, 8000; node index.js; $env:MY_VAR = $oldVal }
This takes advantage of:
{ ... }
is a script block that provides a clearly visible grouping for the commands in it; invoked with&
, it creates a local scope, so that helper variable$oldVal
automatically goes out of scope on exiting the block.$oldVal, $env:MY_VAR = $env:MY_VAR, 8000
saves the old value (if any) of$env:MY_VAR
in$oldVal
while changing the value to8000
; this technique of assigning to multiple variables at once (known as destructuring assignment in some languages) is explained inGet-Help about_Assignment_Operators
, section "ASSIGNING MULTIPLE VARIALBES".
Alternatively, use the helper function below, or use a try { ... } finally { ... }
approach, as demonstrated in this related answer.
Helper function for command-scoped environment modifications.
If you define the helper function below (remember that function definitions must be placed before they're invoked), you can achieve command-scoped modification of your environment as follows:
# Invoke `node index.js` with a *temporarily* set MY_VAR environment variable.
Invoke-WithEnvironment @{ MY_VAR = 8000 } { node index.js }
Invoke-WithEnvironment()
source code:
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]
}
}
}