I'm writing a Chocolately package that needs to install my program and then set a User level environment variable that the program needs.
As recommended in the documentation, I've installed Chocolatey from a PowerShell terminal with elevated privileges. In my chocolatelyinstall.ps1 script I can set the environment variable with this command:
Install-ChocolateyEnvironmentVariable -VariableName "my_env_var" -VariableValue "Wibble" -VariableType User
However, when I install the package: choco install my_package -s .
the environment variable is set at User level for the administrator account, rather than the standard user account.
Installing the package in a regular (non-elevated) PowerShell process, simply fails with:
Access to the path 'C:\ProgramData\chocolatey\lib\my_package\tools' is denied.
Is there any way to set the Env var on the standard user account, rather than the admin account?
All assistance is welcome!
CodePudding user response:
Indeed (to recap), if your elevated process uses a different (of necessity administrative) user account than the current window-station user (the user that started the current OS user session), you cannot define environment variables for the windows-station user using the usual methods that target the HKEY_CURRENT_USER
hive, as it reflects the elevating user's data.
- Conversely, this means that if your window-station user is an administrator and therefore allowed to run with elevation themselves, the problem will not arise.
Workaround (takes the place of your Install-ChocolateyEnvironmentVariable
call):
Determine the identify of the window-station user in terms of its SID (security identify).
Use the SID to target the window-station user's specific registry hive, under
HKEY_USERS
.Use a dummy user-level
[Environment]::SetEnvironmentVariable()
call so as to broadcast a notification of the environment change (modifying the registry directly doesn't do that), notably so that the Windows (GUI) shell refreshes its environment.
# Get the window station user and split into domain name and user name.
$domain, $user = (Get-CimInstance Win32_ComputerSystem).UserName -split '\\'
# Obtain their SID.
$sid = [System.Security.Principal.NTAccount]::new(
$domain,
$user
).Translate([System.Security.Principal.SecurityIdentifier]).Value
# Set an environment variable for them.
Set-ItemProperty "registry::HKEY_USERS\$sid\Environment" my_env_var Wibble
# Set and remove a dummy variable for the *current user*,
# so as to notify the GUI shell that the environment changed.
('unused', $null).ForEach({
[Environment]::SetEnvironmentVariable("_PowerShell_$PID", $_, 'User')
})