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, 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 }
More simply, if there's no preexisting MY_VAR
value that must be restored.
$env:MYVAR=8000; node index.js; $env:MYVAR=$null
# More structured alternative
& { $env:MY_VAR=8000; node index.js; $env:MY_VAR=$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 this GitHub issue); 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 to 8000
; this technique of assigning to multiple variables at once (known as destructuring assignment in some languages) is explained in Get-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 of mine.
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]
}
}
}