Last active
May 18, 2026 08:12
-
-
Save espresso3389/a59eae40b6a0b460fbd510b2dfe3564d to your computer and use it in GitHub Desktop.
A PowerShell script (for Windows), that updates the environment variables; not only the process but the user's environment variables
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
| $envs = @{ | |
| #"CHROME_EXECUTABLE" = "%ProgramFiles%\Google\Chrome Dev\Application\chrome.exe" | |
| "PACKAGES_ROOT" = "D:\.packages" | |
| "PUB_CACHE" = "%PACKAGES_ROOT%\pub" | |
| "npm_config_cache" = "%PACKAGES_ROOT%\npm" | |
| "NUGET_PACKAGES" = "%PACKAGES_ROOT%\nuget" | |
| "BUN_INSTALL_CACHE_DIR" = "%PACKAGES_ROOT%\bun\install\cache" | |
| "VCPKG_DEFAULT_BINARY_CACHE" = "%PACKAGES_ROOT%\vcpkg" | |
| "PIP_CACHE_DIR" = "%PACKAGES_ROOT%\pip" | |
| "GRADLE_USER_HOME" = "%PACKAGES_ROOT%\.gradle" | |
| "MAVEN_OPTS" = "-Dmaven.repo.local=%PACKAGES_ROOT%\maven %MAVEN_OPTS%" | |
| "JAVA_HOME"="%ProgramFiles%\Android\Android Studio\jbr" | |
| "CLAUDE_CODE_GIT_BASH_PATH"="%ProgramFiles%\git\bin\bash.exe" | |
| } | |
| $path = @( | |
| "%USERPROFILE%\.bun\bin" | |
| "%USERPROFILE%\.local\bin" | |
| "D:\flutter\bin" | |
| "%LOCALAPPDATA%\Android\Sdk\platform-tools" | |
| "%PUB_CACHE%\bin" | |
| "%JAVA_HOME%\bin" | |
| ) | |
| # Function to expand environment variables in a string | |
| function Expand-EnvironmentVariables { | |
| param([string]$Value) | |
| return [System.Environment]::ExpandEnvironmentVariables($Value) | |
| } | |
| # Function to broadcast environment variable changes | |
| function Send-EnvironmentChangeMessage { | |
| if (-not ('Win32.NativeMethods' -as [type])) { | |
| Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @' | |
| [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] | |
| public static extern IntPtr SendMessageTimeout( | |
| IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, | |
| uint fuFlags, uint uTimeout, out UIntPtr lpdwResult); | |
| '@ | |
| } | |
| $HWND_BROADCAST = [IntPtr]0xffff | |
| $WM_SETTINGCHANGE = 0x1a | |
| $result = [UIntPtr]::Zero | |
| [Win32.NativeMethods]::SendMessageTimeout( | |
| $HWND_BROADCAST, | |
| $WM_SETTINGCHANGE, | |
| [UIntPtr]::Zero, | |
| "Environment", | |
| 2, # SMTO_ABORTIFHUNG | |
| 5000, | |
| [ref]$result | |
| ) | Out-Null | |
| } | |
| # Set environment variables to User registry (without expansion) | |
| $changesCount = 0 | |
| foreach ($entry in $envs.GetEnumerator()) { | |
| $key = $entry.Key | |
| $value = $entry.Value | |
| # Check if the value is different from current registry value (unexpanded) | |
| $regKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Environment", $false) | |
| $currentValue = if ($regKey) { | |
| $regKey.GetValue($key, $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) | |
| } else { | |
| $null | |
| } | |
| if ($regKey) { $regKey.Close() } | |
| if ($currentValue -ne $value) { | |
| # Determine registry type based on whether value contains expandable variables | |
| $regType = if ($value -match '%\w+%') { 'ExpandString' } else { 'String' } | |
| # Set in user registry using Set-ItemProperty | |
| Set-ItemProperty -Path "HKCU:\Environment" -Name $key -Value $value -Type $regType | |
| $changesCount++ | |
| } | |
| # Expand for display and current process | |
| $expandedValue = Expand-EnvironmentVariables $value | |
| # Set in current process (expanded) | |
| Set-Item -Path "env:$key" -Value $expandedValue | |
| } | |
| # Get current user PATH from registry (unexpanded) | |
| $regKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Environment", $false) | |
| $currentUserPath = if ($regKey) { | |
| $regKey.GetValue("Path", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames) | |
| } else { | |
| "" | |
| } | |
| if ($regKey) { $regKey.Close() } | |
| # Convert to array and filter out empties | |
| $pathArray = if ($currentUserPath) { | |
| $currentUserPath -split ';' | Where-Object { $_ -ne '' } | |
| } else { | |
| @() | |
| } | |
| # Add new paths if they don't already exist (compare expanded versions) | |
| $pathModified = $false | |
| $expandedPathArray = $pathArray | ForEach-Object { Expand-EnvironmentVariables $_ } | |
| $newPathArray = @() | |
| foreach ($newPath in $path) { | |
| $expandedNewPath = Expand-EnvironmentVariables $newPath | |
| if ($expandedPathArray -notcontains $expandedNewPath) { | |
| $newPathArray += $newPath | |
| $expandedPathArray += $expandedNewPath | |
| $pathModified = $true | |
| } | |
| } | |
| # Update user PATH in registry if modified | |
| if ($pathModified) { | |
| $newUserPath = ($newPathArray + $pathArray) -join ';' | |
| Set-ItemProperty -Path "HKCU:\Environment" -Name "Path" -Value $newUserPath -Type ExpandString | |
| $changesCount++ | |
| } | |
| # Update current process PATH with expanded values | |
| $processPathArray = @() | |
| foreach ($p in $pathArray) { | |
| $expanded = Expand-EnvironmentVariables $p | |
| if ($expanded) { | |
| $processPathArray += $expanded | |
| } | |
| } | |
| # Add existing system paths to avoid breaking current session | |
| $systemPath = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine) | |
| if ($systemPath) { | |
| $systemPaths = $systemPath -split ';' | Where-Object { $_ -ne '' } | |
| foreach ($sysPath in $systemPaths) { | |
| if ($processPathArray -notcontains $sysPath) { | |
| $processPathArray += $sysPath | |
| } | |
| } | |
| } | |
| $env:Path = $processPathArray -join ';' | |
| # Broadcast the environment change to all windows only if changes were made | |
| if ($changesCount -gt 0) { | |
| Send-EnvironmentChangeMessage | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment