先关掉 Windows Terminal 和 Codex 再执行下面命令。
这套命令做的是“固定默认入口到新版 pwsh”,不替换系统自带的
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 文件本体。
1. 下载并校验 PowerShell 7.6.0 ZIP
$ProgressPreference = 'SilentlyContinue'
$ver = '7.6.0'
$expected = '9E725837AF682B87BB212CD1EFE3657C06C540404203810857EC2516AE2CA322'
$tmp = Join-Path $env:USERPROFILE '.codex\tmp\pwsh-install'
$zip = Join-Path $tmp "PowerShell-$ver-win-x64.zip"
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
Invoke-WebRequest -Uri "https://github.com/PowerShell/PowerShell/releases/download/v$ver/PowerShell-$ver-win-x64.zip" -OutFile $zip
$actual = (Get-FileHash -Algorithm SHA256 $zip).Hash
$actual
if ($actual -ne $expected) { throw "SHA256 不匹配: $actual" }
2. 解压到当前用户目录
$ver = '7.6.0'
$tmp = Join-Path $env:USERPROFILE '.codex\tmp\pwsh-install'
$zip = Join-Path $tmp "PowerShell-$ver-win-x64.zip"
$base = Join-Path $env:LOCALAPPDATA "Programs\PowerShell\$ver"
$pwsh = Join-Path $base 'pwsh.exe'
New-Item -ItemType Directory -Force -Path $base | Out-Null
tar.exe -xf $zip -C $base
& $pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()'
3. 把用户级 PATH 和 SHELL 指到新版 pwsh
$ver = '7.6.0'
$base = Join-Path $env:LOCALAPPDATA "Programs\PowerShell\$ver"
$pwsh = Join-Path $base 'pwsh.exe'
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
if (-not $userPath) { $userPath = '' }
$parts = $userPath -split ';' | Where-Object { $_ }
if ($parts -notcontains $base) {
$newPath = if ($userPath) { "$base;$userPath" } else { $base }
[Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
}
[Environment]::SetEnvironmentVariable('SHELL', $pwsh, 'User')
[Environment]::GetEnvironmentVariable('SHELL', 'User')
[Environment]::GetEnvironmentVariable('Path', 'User')
4. 固定 Windows Terminal 默认 Profile 到新版 pwsh
$ver = '7.6.0'
$base = Join-Path $env:LOCALAPPDATA "Programs\PowerShell\$ver"
$pwsh = Join-Path $base 'pwsh.exe'
$wtDir = Join-Path $env:LOCALAPPDATA 'Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState'
$wt = Join-Path $wtDir 'settings.json'
$bak = Join-Path $wtDir ("settings.json.bak." + (Get-Date -Format 'yyyyMMdd_HHmmss'))
$guid = '{4b0c710a-8d30-4b7f-9f1f-0b4f9e0f7600}'
New-Item -ItemType Directory -Force -Path $wtDir | Out-Null
if (Test-Path $wt) { Copy-Item $wt $bak -Force }
@"
{
"`$schema": "https://aka.ms/terminal-profiles-schema",
"defaultProfile": "$guid",
"profiles": {
"list": [
{
"guid": "$guid",
"name": "PowerShell $ver",
"commandline": "$($pwsh -replace '\\','\\')",
"icon": "$($pwsh -replace '\\','\\')",
"hidden": false
},
{
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"name": "Windows PowerShell",
"hidden": true
}
]
}
}
"@ | Set-Content -Path $wt -Encoding utf8
Get-Content $wt -Raw
5. 把 Win11 默认终端应用切到 Windows Terminal
$k = 'HKCU:\Console\%%Startup'
New-Item -Path $k -Force | Out-Null
Set-ItemProperty -Path $k -Name DelegationConsole -Value '{2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69}'
Set-ItemProperty -Path $k -Name DelegationTerminal -Value '{E12CFF52-A866-4C77-9A90-F570A7AA2C6B}'
Get-ItemProperty $k | Format-List DelegationConsole,DelegationTerminal
6. 把开始菜单里的 Windows PowerShell 快捷方式改到新版 pwsh
$ver = '7.6.0'
$base = Join-Path $env:LOCALAPPDATA "Programs\PowerShell\$ver"
$pwsh = Join-Path $base 'pwsh.exe'
$dir = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs\Windows PowerShell'
$backup = Join-Path $dir '_backup_codex_manual'
$wsh = New-Object -ComObject WScript.Shell
New-Item -ItemType Directory -Force -Path $backup | Out-Null
Get-ChildItem $dir -Filter '*.lnk' | ForEach-Object {
Copy-Item $_.FullName -Destination (Join-Path $backup $_.Name) -Force
$s = $wsh.CreateShortcut($_.FullName)
$s.TargetPath = $pwsh
$s.Arguments = ''
$s.IconLocation = "$pwsh,0"
$s.WorkingDirectory = $env:USERPROFILE
$s.Save()
}
Get-ChildItem $dir -Filter '*.lnk' | ForEach-Object {
$s = $wsh.CreateShortcut($_.FullName)
[PSCustomObject]@{
Name = $_.Name
TargetPath = $s.TargetPath
IconLocation = $s.IconLocation
}
} | Format-List
7. 把 Win+X / 开始按钮右键菜单里的 Windows PowerShell 快捷方式改到新版 pwsh
$ver = '7.6.0'
$base = Join-Path $env:LOCALAPPDATA "Programs\PowerShell\$ver"
$pwsh = Join-Path $base 'pwsh.exe'
$dir = Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\WinX\Group3'
$backup = Join-Path $dir '_backup_codex_manual'
$wsh = New-Object -ComObject WScript.Shell
New-Item -ItemType Directory -Force -Path $backup | Out-Null
Get-ChildItem $dir -Filter '*Windows PowerShell.lnk' | ForEach-Object {
Copy-Item $_.FullName -Destination (Join-Path $backup $_.Name) -Force
$s = $wsh.CreateShortcut($_.FullName)
$s.TargetPath = $pwsh
$s.Arguments = ''
$s.IconLocation = "$pwsh,0"
$s.WorkingDirectory = $env:USERPROFILE
$s.Save()
}
Get-ChildItem $dir -Filter '*Windows PowerShell.lnk' | ForEach-Object {
$s = $wsh.CreateShortcut($_.FullName)
[PSCustomObject]@{
Name = $_.Name
TargetPath = $s.TargetPath
IconLocation = $s.IconLocation
}
} | Format-List
8. 重启 Explorer 刷新菜单缓存
Stop-Process -Name explorer -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
Start-Process explorer.exe
9. 验证版本、编码、快捷方式目标
$ver = '7.6.0'
$base = Join-Path $env:LOCALAPPDATA "Programs\PowerShell\$ver"
$pwsh = Join-Path $base 'pwsh.exe'
& $pwsh -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString(); Write-Output ("UTF8=" + [Console]::OutputEncoding.WebName); Write-Output "中文正常"'
$wsh = New-Object -ComObject WScript.Shell
$paths = @(
(Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs\Windows PowerShell\Windows PowerShell.lnk'),
(Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\WinX\Group3\01a - Windows PowerShell.lnk'),
(Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\WinX\Group3\02a - Windows PowerShell.lnk')
)
$paths | ForEach-Object {
$s = $wsh.CreateShortcut($_)
[PSCustomObject]@{
Path = $_
TargetPath = $s.TargetPath
IconLocation = $s.IconLocation
}
} | Format-List
10. 重启 Codex
Write-Output '现在手动关闭并重新打开 Codex,新会话会吃到新版默认值。'
11. 可选:恢复备份
$startDir = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs\Windows PowerShell'
$startBak = Join-Path $startDir '_backup_codex_manual'
Get-ChildItem $startBak -Filter '*.lnk' | ForEach-Object {
Copy-Item $_.FullName -Destination (Join-Path $startDir $_.Name) -Force
}
$winxDir = Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\WinX\Group3'
$winxBak = Join-Path $winxDir '_backup_codex_manual'
Get-ChildItem $winxBak -Filter '*.lnk' | ForEach-Object {
Copy-Item $_.FullName -Destination (Join-Path $winxDir $_.Name) -Force
}
Stop-Process -Name explorer -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
Start-Process explorer.exe