2026-06-11

[PS]因為某些失誤不小心把系統環境變數Path全部刪除刪除

環境變數分為使用者變數與系統變數,以下為新增系統變數Path,並且可以放到GPO的版本
  • 因為放到GPO當重覆不能重覆新增
  • 原本有的Path內容,不會被覆蓋
  • 如果Path內容,有參數問題,也不會造成判斷錯誤,例如%Windows%
  • 大小寫不會判斷錯誤
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"

# 1. 讀取目前「活著」的原始 PATH(如果完全沒有,則給予空字串,防止 Null 崩潰)
$currentPath = ""
if (Get-ItemProperty -Path $regPath -Name PATH -ErrorAction SilentlyContinue) {
    $currentPath = (Get-ItemProperty -Path $regPath -Name PATH).PATH
}

# 2. 定義系統核心路徑與應用程式路徑
$essentialPaths = @(
    "%SystemRoot%\system32",
    "%SystemRoot%",
    "%SystemRoot%\System32\Wbem",
    "%SystemRoot%\System32\WindowsPowerShell\v1.0\",
    "%SystemRoot%\System32\OpenSSH\",
    "C:\Program Files (x86)\Microsoft\Edge\Application",
    "C:\Program Files (x86)\Common Files\Oracle\Java\java8path",
    "C:\Program Files (x86)\Common Files\Oracle\Java\javapath"
)

# 3. 將目前現有的 PATH 切開成陣列,統一轉小寫並剔除結尾斜線
$currentPathArray = $currentPath -split ';' | ForEach-Object { $_.Trim().ToLower().TrimEnd('\') }

# 3.5 額外產生一個「已經把 %SystemRoot% 換成 C:\Windows」的現有路徑陣列,用來雙重防禦
$expandedCurrentPathArray = $currentPathArray | ForEach-Object { 
    [Environment]::ExpandEnvironmentVariables($_).ToLower().TrimEnd('\') 
}

# 4. 用來累積存放「目前漏掉、需要補上去」的路徑購物車
$pathsToAppend = @()

foreach ($path in $essentialPaths) {
    # 將我們要檢查的路徑,分別製作「未展開小寫」與「已展開小寫」兩種版本
    $cleanPath = $path.ToLower().TrimEnd('\')
    $expandedPath = [Environment]::ExpandEnvironmentVariables($path).ToLower().TrimEnd('\')
    
    # 【核心修正】:如果現有的 PATH 裡面,既沒有原始變數格式,也沒有展開後的 C:\ 格式,才允許加入!
    if ($currentPathArray -notcontains $cleanPath -and $expandedCurrentPathArray -notcontains $expandedPath) {
        $pathsToAppend += $path
    }
}

# 5. 如果有發現缺少的路徑,才進行更新
if ($pathsToAppend.Count -gt 0) {
    
    # 判斷原本的 PATH 是不是空的
    if ([string]::IsNullOrWhiteSpace($currentPath)) {
        $newPath = $pathsToAppend -join ";"
    } else {
        # 確保原本使用者自己裝的軟體路徑完全不會被動到
        $newPath = $currentPath.Trim(';') + ";" + ($pathsToAppend -join ";")
    }
    
    # 6. 強制指定以 ExpandString (REG_EXPAND_SZ) 寫入,保護 %SystemRoot% 變數不變死字串
    Set-ItemProperty -Path $regPath -Name PATH -Value $newPath -Type ExpandString
    
    Write-Host "成功!已保留原本的所有路徑,並補上缺少的:($($pathsToAppend -join ', '))" -ForegroundColor Green
    
    # 7. 通知 Windows 系統更新環境變數(免重開機立即生效)
    $signature = '[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);'
    $win32 = Add-Type -MemberDefinition $signature -Name "Win32" -Namespace "Env" -PassThru
    $result = [UIntPtr]::Zero
    $win32::SendMessageTimeout([IntPtr]0xffff, 0x001A, [UIntPtr]::Zero, "Environment", 2, 5000, [ref]$result) | Out-Null

} else {
    Write-Host "檢查完畢:所有核心路徑與指定路徑已存在(包含變數展開檢查),未重複新增。" -ForegroundColor Yellow
}
補充其他系統變數的Path
npm 與node 無法執行要加入C:\Program Files\nodejs
choco無法執行要加入C:\ProgramData\chocolatey\bin

沒有留言:

張貼留言