From c58646325c91f6c64b130879468f932c7aa01725 Mon Sep 17 00:00:00 2001 From: Michael Nadel Date: Wed, 3 Jun 2015 21:51:55 -0500 Subject: [PATCH 1/2] (GH-303) Install-ChocolateyPath - Do Not Expand Variables in PATH When adding a new element to PATH, Install-ChocolateyPath reads PATH (wh ich contains expanded variables), appends the new element, and then writes the value back to PATH. This results in PATH having its variables overwritten with its values. Instead of reading $env:PATH to find the current path, read it from the registry, which will retain the PATH's original variables. --- .../functions/Get-EnvironmentVariable.ps1 | 32 ++++++++++++++----- .../functions/Install-ChocolateyPath.ps1 | 6 ++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 b/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 index 3a2079a6fa..89e1fb0562 100644 --- a/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 +++ b/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 @@ -10,11 +10,27 @@ # 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. - -function Get-EnvironmentVariable([string] $Name, [System.EnvironmentVariableTarget] $Scope) { - [Environment]::GetEnvironmentVariable($Name, $Scope) -} - -# Some enhancements to think about here. -# $machinePath = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment\").GetValue("PATH", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames).ToString(); +# limitations under the License. + +function Get-EnvironmentVariable([string] $Name, [System.EnvironmentVariableTarget] $Scope, [bool] $PreserveVariables = $False) { + if ($pathType -eq [System.EnvironmentVariableTarget]::Machine) { + $reg = [Microsoft.Win32.Registry]::Machine.OpenSubKey("Environment", $true) + } else { + $reg = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Environment", $true) + } + + if ($PreserveVariables -eq $True) { + $option = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames + } else { + $option = [Microsoft.Win32.RegistryValueOptions]::None + } + + $value = $reg.GetValue('Path', $null, $option) + + $reg.Close() + + return $value +} + +# Some enhancements to think about here. +# $machinePath = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment\").GetValue("PATH", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames).ToString(); diff --git a/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 b/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 index 5e0f4370ec..37b145cadb 100644 --- a/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 +++ b/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 @@ -10,8 +10,8 @@ # 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. - +# limitations under the License. + function Install-ChocolateyPath { param( [string] $pathToInstall, @@ -26,7 +26,7 @@ param( if (!$envPath.ToLower().Contains($pathToInstall.ToLower())) { Write-Host "PATH environment variable does not have $pathToInstall in it. Adding..." - $actualPath = Get-EnvironmentVariable -Name 'Path' -Scope $pathType + $actualPath = Get-EnvironmentVariable -Name 'Path' -Scope $pathType -PreserveVariables $True $statementTerminator = ";" #does the path end in ';'? From 9bbfb4e882111bffb5f910b267f0e09ad10b95af Mon Sep 17 00:00:00 2001 From: Fernando Tirolo Gomes Date: Sat, 9 Apr 2016 12:42:08 -0500 Subject: [PATCH 2/2] (GH-303) Get-EnvironmentVariable Changes - Declare argument as `switch` instead of `bool`. - Renamed some variables and added comments. - Updated references to Get-EnvironmentVariable. - Cleaned up formatting. - Allowed getting process scoped environment variables again. --- .../functions/Get-EnvironmentVariable.ps1 | 74 ++++++++++++++----- .../functions/Install-ChocolateyPath.ps1 | 2 +- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 b/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 index 89e1fb0562..c4e328d79b 100644 --- a/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 +++ b/src/chocolatey.resources/helpers/functions/Get-EnvironmentVariable.ps1 @@ -12,25 +12,65 @@ # See the License for the specific language governing permissions and # limitations under the License. -function Get-EnvironmentVariable([string] $Name, [System.EnvironmentVariableTarget] $Scope, [bool] $PreserveVariables = $False) { - if ($pathType -eq [System.EnvironmentVariableTarget]::Machine) { - $reg = [Microsoft.Win32.Registry]::Machine.OpenSubKey("Environment", $true) - } else { - $reg = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Environment", $true) - } +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). + +.PARAMETER Name +The environemnt variable you want to get the value from. + +.PARAMETER Scope +The environemnt variable target scope. + +.PARAMETER PreserveVariables +A switch parameter stating whether you want to expand the variables or not. Defaults to false. + +.EXAMPLE +Get-EnvironmentVariable 'TEMP' User -PreserveVariables + +.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. +#> +[CmdletBinding()] +[OutputType([string])] +param( + [Parameter(Mandatory=$true)] + [string] $Name, + [Parameter(Mandatory=$true)] + [System.EnvironmentVariableTarget] $Scope, + [Parameter(Mandatory=$false)] + [switch] $PreserveVariables = $false +) + [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) { + [Environment]::GetEnvironmentVariable($Name, $Scope) + } - if ($PreserveVariables -eq $True) { - $option = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames - } else { - $option = [Microsoft.Win32.RegistryValueOptions]::None - } + [Microsoft.Win32.RegistryValueOptions] $registryValueOptions = [Microsoft.Win32.RegistryValueOptions]::None - $value = $reg.GetValue('Path', $null, $option) + if ($PreserveVariables) { + Write-Verbose "Choosing not to expand environment names" + $registryValueOptions = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames + } - $reg.Close() + [string] $environmentVariableValue = [string]::Empty - return $value -} + try { + Write-Verbose "Getting environment variable $Name" + $environmentVariableValue = $win32RegistryKey.GetValue($Name, [string]::Empty, $registryValueOptions) + } catch { + Write-Debug "Unable to retrieve the $Name environment variable. Details: $_" + } finally { + $win32RegistryKey.Close() + } -# Some enhancements to think about here. -# $machinePath = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment\").GetValue("PATH", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames).ToString(); + return $environmentVariableValue +} \ No newline at end of file diff --git a/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 b/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 index 37b145cadb..2f6153c17a 100644 --- a/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 +++ b/src/chocolatey.resources/helpers/functions/Install-ChocolateyPath.ps1 @@ -26,7 +26,7 @@ param( if (!$envPath.ToLower().Contains($pathToInstall.ToLower())) { Write-Host "PATH environment variable does not have $pathToInstall in it. Adding..." - $actualPath = Get-EnvironmentVariable -Name 'Path' -Scope $pathType -PreserveVariables $True + $actualPath = Get-EnvironmentVariable -Name 'Path' -Scope $pathType -PreserveVariables $statementTerminator = ";" #does the path end in ';'?