fix(win): prevent user PATH clobbering and normalize gateway PATH env (#459)
This commit is contained in:
@@ -9,6 +9,39 @@ param(
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Get-UserPathRegistryValue {
|
||||
$raw = [Environment]::GetEnvironmentVariable('Path', 'User')
|
||||
$kind = [Microsoft.Win32.RegistryValueKind]::ExpandString
|
||||
|
||||
try {
|
||||
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $false)
|
||||
if ($null -ne $key) {
|
||||
try {
|
||||
$stored = $key.GetValue('Path', $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
||||
if ($null -ne $stored) {
|
||||
$raw = [string]$stored
|
||||
}
|
||||
} catch {
|
||||
# Fallback to Environment API value
|
||||
}
|
||||
|
||||
try {
|
||||
$kind = $key.GetValueKind('Path')
|
||||
} catch {
|
||||
# Keep default ExpandString
|
||||
}
|
||||
$key.Close()
|
||||
}
|
||||
} catch {
|
||||
# Fallback to Environment API value
|
||||
}
|
||||
|
||||
return @{
|
||||
Raw = $raw
|
||||
Kind = $kind
|
||||
}
|
||||
}
|
||||
|
||||
function Normalize-PathEntry {
|
||||
param([string]$Value)
|
||||
|
||||
@@ -19,7 +52,8 @@ function Normalize-PathEntry {
|
||||
return $Value.Trim().Trim('"').TrimEnd('\').ToLowerInvariant()
|
||||
}
|
||||
|
||||
$current = [Environment]::GetEnvironmentVariable('Path', 'User')
|
||||
$pathMeta = Get-UserPathRegistryValue
|
||||
$current = $pathMeta.Raw
|
||||
$entries = @()
|
||||
if (-not [string]::IsNullOrWhiteSpace($current)) {
|
||||
$entries = $current -split ';' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
|
||||
@@ -54,35 +88,63 @@ if ($Action -eq 'add') {
|
||||
$status = 'updated'
|
||||
}
|
||||
|
||||
$newPath = if ($nextEntries.Count -eq 0) { $null } else { $nextEntries -join ';' }
|
||||
[Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
|
||||
|
||||
Add-Type -Namespace OpenClaw -Name NativeMethods -MemberDefinition @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
public static class NativeMethods {
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr SendMessageTimeout(
|
||||
IntPtr hWnd,
|
||||
int Msg,
|
||||
IntPtr wParam,
|
||||
string lParam,
|
||||
int fuFlags,
|
||||
int uTimeout,
|
||||
out IntPtr lpdwResult
|
||||
);
|
||||
$isLikelyCorruptedWrite = (
|
||||
$Action -eq 'add' -and
|
||||
$entries.Count -gt 1 -and
|
||||
$nextEntries.Count -le 1
|
||||
)
|
||||
if ($isLikelyCorruptedWrite) {
|
||||
throw "Refusing to rewrite user PATH: input had $($entries.Count) entries but output has $($nextEntries.Count)."
|
||||
}
|
||||
|
||||
$newPath = if ($nextEntries.Count -eq 0) { $null } else { $nextEntries -join ';' }
|
||||
try {
|
||||
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true)
|
||||
if ($null -eq $key) {
|
||||
throw 'Unable to open HKCU\Environment for write.'
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($newPath)) {
|
||||
$key.DeleteValue('Path', $false)
|
||||
} else {
|
||||
$kind = if ($pathMeta.Kind -eq [Microsoft.Win32.RegistryValueKind]::String) {
|
||||
[Microsoft.Win32.RegistryValueKind]::String
|
||||
} else {
|
||||
[Microsoft.Win32.RegistryValueKind]::ExpandString
|
||||
}
|
||||
$key.SetValue('Path', $newPath, $kind)
|
||||
}
|
||||
$key.Close()
|
||||
} catch {
|
||||
throw "Failed to write HKCU\\Environment\\Path: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
try {
|
||||
Add-Type -Namespace OpenClaw -Name NativeMethods -MemberDefinition @"
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
|
||||
public static extern System.IntPtr SendMessageTimeout(
|
||||
System.IntPtr hWnd,
|
||||
int Msg,
|
||||
System.IntPtr wParam,
|
||||
string lParam,
|
||||
int fuFlags,
|
||||
int uTimeout,
|
||||
out System.IntPtr lpdwResult
|
||||
);
|
||||
"@
|
||||
|
||||
$result = [IntPtr]::Zero
|
||||
[OpenClaw.NativeMethods]::SendMessageTimeout(
|
||||
[IntPtr]0xffff,
|
||||
0x001A,
|
||||
[IntPtr]::Zero,
|
||||
'Environment',
|
||||
0x0002,
|
||||
5000,
|
||||
[ref]$result
|
||||
) | Out-Null
|
||||
$result = [IntPtr]::Zero
|
||||
[OpenClaw.NativeMethods]::SendMessageTimeout(
|
||||
[IntPtr]0xffff,
|
||||
0x001A,
|
||||
[IntPtr]::Zero,
|
||||
'Environment',
|
||||
0x0002,
|
||||
5000,
|
||||
[ref]$result
|
||||
) | Out-Null
|
||||
} catch {
|
||||
Write-Warning "PATH updated but failed to broadcast environment change: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
Write-Output $status
|
||||
|
||||
Reference in New Issue
Block a user