Created
October 10, 2018 02:27
-
-
Save mklement0/a71eee0f61213935937173b52defd778 to your computer and use it in GitHub Desktop.
PowerShell script/function that invokes a command with a temporarily modified environment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, restored afterwards. | |
#> | |
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] | |
} | |
} | |
} | |
# -- Generic code that handles the invocation. | |
if ($MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq '') { # Being dot-sourced | |
if ($MyInvocation.Line -eq '' -and $host.Name -eq 'Visual Studio Code Host') { # Support for debugging in VSCode | |
# If the current file is directly launched for debugging from the editor, | |
# use a custom invocation with arguments for debugging. | |
Write-Warning 'VSCode debugging: Invoking embedded function with custom arguments.' | |
& ([System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath)) # Add arguments for debugging here. | |
} else { | |
# Nothing further to do: the function has been defined in the current scope for *later* use. | |
# However, we warn if arguments were unexpectedly passed or something is being piped. | |
if ($Args.Count -or $MyInvocation.ExpectingInput) { Write-Warning "Ignoring arguments and/or pipeline input due to being dot-sourced: $PSCommandPath" } | |
} | |
} else { # Script is invoked directly (by name/path directly or via &) | |
# Call the embedded function of the same name, relaying any arguments passed. | |
if ($MyInvocation.ExpectingInput) { # pipeline input present | |
$Input | & ([System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath)) @Args | |
} else { # only arguments, if any | |
& ([System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath)) @Args | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment