TroubleChute Logo
< Go Back

TroubleChute Script Hub

Currently viewing: PowerShell/General/refreshenv.ps1


NOTE: The following code may be out-of-date compared to GitHub, but is all pulled from GitHub every hour or so.

When shortlinks are used (filename as subdomain), code used by PowerShell and other interactions with this site is served from GitHub.

(Right-click -> Download the button below to save the file)

Last modified: 2023-04-12T20:59:52.000+02:00

refreshenv.ps1
# This function sets the Alias for "refreshenv" based on "Update-SessionEnvironment" from the Chocolatey program.

# Copyright � 2017 - 2021 Chocolatey Software, Inc.
# Copyright � 2015 - 2017 RealDimensions Software, LLC
# Copyright � 2011 - 2015 RealDimensions Software, LLC & original authors/contributors from https://github.com/chocolatey/chocolatey
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ----------------------------------------
## From Choco: https://github.com/chocolatey/choco/blob/stable/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariableNames.ps1
# ----------------------------------------

function Get-EnvironmentVariableNames([System.EnvironmentVariableTarget] $Scope) {
<#
.SYNOPSIS
Gets all environment variable names.
.DESCRIPTION
Provides a list of environment variable names based on the scope. This
can be used to loop through the list and generate names.
.NOTES
Process dumps the current environment variable names in memory /
session. The other scopes refer to the registry values.
.INPUTS
None
.OUTPUTS
A list of environment variables names.
.PARAMETER Scope
The environment variable target scope. This is `Process`, `User`, or
`Machine`.
.EXAMPLE
Get-EnvironmentVariableNames -Scope Machine
.LINK
Get-EnvironmentVariable
.LINK
Set-EnvironmentVariable
#>

  # Do not log function call

  # HKCU:\Environment may not exist in all Windows OSes (such as Server Core).
  switch ($Scope) {
    'User' { Get-Item 'HKCU:\Environment' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Property }
    'Machine' { Get-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' | Select-Object -ExpandProperty Property }
    'Process' { Get-ChildItem Env:\ | Select-Object -ExpandProperty Key }
    default { throw "Unsupported environment scope: $Scope" }
  }
}


## From Choco: https://github.com/chocolatey/choco/blob/stable/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1

function Get-EnvironmentVariable {
<#
.SYNOPSIS
Gets an Environment Variable.

.DESCRIPTION
This will will get an environment variable based on the variable name
and scope while accounting whether to expand the variable or not
(e.g.: `%TEMP%`-> `C:\User\Username\AppData\Local\Temp`).

.NOTES
This helper reduces the number of lines one would have to write to get
environment variables, mainly when not expanding the variables is a
must.

.PARAMETER Name
The environment variable you want to get the value from.

.PARAMETER Scope
The environment variable target scope. This is `Process`, `User`, or
`Machine`.

.PARAMETER PreserveVariables
A switch parameter stating whether you want to expand the variables or
not. Defaults to false. Available in 0.9.10+.

.PARAMETER IgnoredArguments
Allows splatting with arguments that do not apply. Do not use directly.

.EXAMPLE
Get-EnvironmentVariable -Name 'TEMP' -Scope User -PreserveVariables

.EXAMPLE
Get-EnvironmentVariable -Name 'PATH' -Scope Machine

.LINK
Get-EnvironmentVariableNames

.LINK
Set-EnvironmentVariable
#>
[CmdletBinding()]
[OutputType([string])]
param(
  [Parameter(Mandatory=$true)][string] $Name,
  [Parameter(Mandatory=$true)][System.EnvironmentVariableTarget] $Scope,
  [Parameter(Mandatory=$false)][switch] $PreserveVariables = $false,
  [parameter(ValueFromRemainingArguments = $true)][Object[]] $ignoredArguments
)

  # Do not log function call, it may expose variable names
  ## Called from chocolateysetup.psm1 - wrap any Write-Host in try/catch

  [string] $MACHINE_ENVIRONMENT_REGISTRY_KEY_NAME = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment\";
  [Microsoft.Win32.RegistryKey] $win32RegistryKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($MACHINE_ENVIRONMENT_REGISTRY_KEY_NAME)
  if ($Scope -eq [System.EnvironmentVariableTarget]::User) {
    [string] $USER_ENVIRONMENT_REGISTRY_KEY_NAME = "Environment";
    [Microsoft.Win32.RegistryKey] $win32RegistryKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($USER_ENVIRONMENT_REGISTRY_KEY_NAME)
  } elseif ($Scope -eq [System.EnvironmentVariableTarget]::Process) {
    return [Environment]::GetEnvironmentVariable($Name, $Scope)
  }

  [Microsoft.Win32.RegistryValueOptions] $registryValueOptions = [Microsoft.Win32.RegistryValueOptions]::None

  if ($PreserveVariables) {
    Write-Verbose "Choosing not to expand environment names"
    $registryValueOptions = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
  }

  [string] $environmentVariableValue = [string]::Empty

  try {
    #Write-Verbose "Getting environment variable $Name"
    if ($win32RegistryKey -ne $null) {
      # Some versions of Windows do not have HKCU:\Environment
      $environmentVariableValue = $win32RegistryKey.GetValue($Name, [string]::Empty, $registryValueOptions)
    }
  } catch {
    Write-Debug "Unable to retrieve the $Name environment variable. Details: $_"
  } finally {
    if ($win32RegistryKey -ne $null) {
      $win32RegistryKey.Close()
    }
  }

  if ($environmentVariableValue -eq $null -or $environmentVariableValue -eq '') {
    $environmentVariableValue = [Environment]::GetEnvironmentVariable($Name, $Scope)
  }

  return $environmentVariableValue
}


## From Choco: https://github.com/chocolatey/choco/blob/stable/src/chocolatey.resources/helpers/functions/Update-SessionEnvironment.ps1

function Update-SessionEnvironment {
<#
.SYNOPSIS
Updates the environment variables of the current powershell session with
any environment variable changes that may have occured during a
Chocolatey package install.

.DESCRIPTION
When Chocolatey installs a package, the package author may add or change
certain environment variables that will affect how the application runs
or how it is accessed. Often, these changes are not visible to the
current PowerShell session. This means the user needs to open a new
PowerShell session before these settings take effect which can render
the installed application nonfunctional until that time.

Use the Update-SessionEnvironment command to refresh the current
PowerShell session with all environment settings possibly performed by
Chocolatey package installs.

.NOTES
This method is also added to the user's PowerShell profile as
`refreshenv`. When called as `refreshenv`, the method will provide
additional output.

Preserves `PSModulePath` as set by the process starting in 0.9.10.

.INPUTS
None

.OUTPUTS
None
#>

  $refreshEnv = $false
  $invocation = $MyInvocation
  if ($invocation.InvocationName -eq 'refreshenv') {
    $refreshEnv = $true
  }

  if ($refreshEnv) {
    Write-Output 'Refreshing environment variables from the registry for powershell.exe. Please wait...'
  } else {
    Write-Verbose 'Refreshing environment variables from the registry.'
  }

  $userName = $env:USERNAME
  $architecture = $env:PROCESSOR_ARCHITECTURE
  $psModulePath = $env:PSModulePath

  #ordering is important here, $user should override $machine...
  $ScopeList = 'Process', 'Machine'
  if ($userName -notin 'SYSTEM', "${env:COMPUTERNAME}`$") {
    # but only if not running as the SYSTEM/machine in which case user can be ignored.
    $ScopeList += 'User'
  }
  foreach ($Scope in $ScopeList) {
    Get-EnvironmentVariableNames -Scope $Scope |
        ForEach-Object {
          Set-Item "Env:$_" -Value (Get-EnvironmentVariable -Scope $Scope -Name $_)
        }
  }

  #Path gets special treatment b/c it munges the two together
  $paths = 'Machine', 'User' |
    ForEach-Object {
      (Get-EnvironmentVariable -Name 'PATH' -Scope $_) -split ';'
    } |
    Select-Object -Unique
  $Env:PATH = $paths -join ';'

  # PSModulePath is almost always updated by process, so we want to preserve it.
  $env:PSModulePath = $psModulePath

  # reset user and architecture
  if ($userName) { $env:USERNAME = $userName; }
  if ($architecture) { $env:PROCESSOR_ARCHITECTURE = $architecture; }

  if ($refreshEnv) {
    Write-Output 'Finished'
  }
}

Set-Alias refreshenv Update-SessionEnvironment

TCNO TechNobo / TroubleChute © Wesley Pyburn (TroubleChute)
Support Me Privacy Policy Cookies Policy Terms of Service Contact