Append to User PATH by default, close $envKey in finally

Add-ToUserPath gains a -Position Append|Prepend parameter defaulting to
Append so installing unsloth no longer prepends the bundled venv Scripts
directory ahead of the user's existing python / pip on new shells. The
four current call sites (install.ps1 launcher, studio/setup.ps1 CMake,
nvcc, Python user Scripts) all take the Append default because each one
that needs in-session precedence already does an inline $env:Path prepend
independently. This matches rustup / cargo / nvm / pyenv / uv behavior.

Also wrap the script-top $envKey.GetValue in a try/finally so the
registry handle is released even if the read throws. Matches the pattern
already used for $backupKey five lines below.
This commit is contained in:
Daniel Han 2026-04-16 08:05:37 +00:00
commit 42beb1e91f
2 changed files with 37 additions and 6 deletions

View file

@ -134,9 +134,19 @@ function Install-UnslothStudio {
# ── Helper: safely add a directory to the persistent User PATH ──
# Uses direct registry access to preserve REG_EXPAND_SZ type
# (avoids .NET SetEnvironmentVariable bug that converts to REG_SZ).
#
# Position: 'Append' (default) adds $Directory to the END of the persisted
# User PATH so existing user tools (e.g. system python, pip) keep taking
# precedence in new shells. This matches rustup/cargo/nvm/pyenv/uv behavior
# and avoids silently hijacking resolution of common executables. Pass
# 'Prepend' only when a caller truly needs the new entry to win over
# existing ones at registry scope. In-session precedence should be handled
# by an inline $env:Path = "$Dir;$env:Path" prepend instead.
function Add-ToUserPath {
param(
[Parameter(Mandatory = $true)][string]$Directory
[Parameter(Mandatory = $true)][string]$Directory,
[ValidateSet('Append','Prepend')]
[string]$Position = 'Append'
)
try {
$regKey = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
@ -171,7 +181,11 @@ function Install-UnslothStudio {
if (-not $rawPath) {
Write-Host "[WARN] User PATH is empty — initializing with $Directory" -ForegroundColor Yellow
}
$newPath = if ($rawPath) { "$Directory;$rawPath" } else { $Directory }
$newPath = if ($rawPath) {
if ($Position -eq 'Prepend') { "$Directory;$rawPath" } else { "$rawPath;$Directory" }
} else {
$Directory
}
$regKey.SetValue('Path', $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
# Broadcast WM_SETTINGCHANGE so other processes pick up the change
try {

View file

@ -104,9 +104,19 @@ function Refresh-Environment {
# ── Helper: safely add a directory to the persistent User PATH ──
# Uses direct registry access to preserve REG_EXPAND_SZ type
# (avoids .NET SetEnvironmentVariable bug that converts to REG_SZ).
#
# Position: 'Append' (default) adds $Directory to the END of the persisted
# User PATH so existing user tools (e.g. system python, pip) keep taking
# precedence in new shells. This matches rustup/cargo/nvm/pyenv/uv behavior
# and avoids silently hijacking resolution of common executables. Pass
# 'Prepend' only when a caller truly needs the new entry to win over
# existing ones at registry scope. In-session precedence should be handled
# by an inline $env:Path = "$Dir;$env:Path" prepend instead.
function Add-ToUserPath {
param(
[Parameter(Mandatory = $true)][string]$Directory
[Parameter(Mandatory = $true)][string]$Directory,
[ValidateSet('Append','Prepend')]
[string]$Position = 'Append'
)
try {
$regKey = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
@ -143,7 +153,11 @@ function Add-ToUserPath {
if (-not $rawPath) {
Write-Host "[WARN] User PATH is empty — initializing with $Directory" -ForegroundColor Yellow
}
$newPath = if ($rawPath) { "$Directory;$rawPath" } else { $Directory }
$newPath = if ($rawPath) {
if ($Position -eq 'Prepend') { "$Directory;$rawPath" } else { "$rawPath;$Directory" }
} else {
$Directory
}
$regKey.SetValue('Path', $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
# Broadcast WM_SETTINGCHANGE so other processes pick up the change
try {
@ -584,8 +598,11 @@ if ($script:StudioVtOk -and -not $env:NO_COLOR) {
try {
$envKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $false)
if ($envKey) {
$rawPath = $envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
$envKey.Close()
try {
$rawPath = $envKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
} finally {
$envKey.Close()
}
if ($rawPath) {
$backupKey = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Software\Unsloth')
try {