很多人的机器上还躺着系统自带的 Windows PowerShell 5.1,每次打开都是一片蓝底白字,敲个命令补全全靠 Tab 硬按,脚本里写个&&还要报错。这时候同事甩过来一句"装个 PowerShell 7 吧",你搜了一圈,发现安装方式五花八门:有包管理器一行命令的,有下载 MSI 双击下一步的,还有解压个 zip 就能跑的。更麻烦的是卸的时候——控制面板里翻不到、装了两个版本不知道删哪个、PATH 里留着一行指向空目录的死路径。这篇就把 PowerShell 7 的安装和卸载从头到尾捋一遍,包括版本通道怎么选、三种安装方式分别在什么场景下用、装完必须做哪几项配置、卸载时哪些残留必须手动清。不管你是刚接触命令行的新手,还是已经写了几年脚本、想把手头环境统一起来的老手,下面这些内容都能直接照着做。
1. 动手之前先想清楚:PowerShell 7 装的是什么
1.1 版本号、发布通道与运行时依赖
PowerShell 7 不是 Windows PowerShell 5.1 的补丁升级,而是一次彻底的重写:底层运行时从 .NET Framework 换成了跨平台的 .NET,可执行文件名也从powershell.exe变成了pwsh.exe。这个改动带来的直接后果是——它可以在 Windows、Linux、macOS 上跑同一套脚本,管道性能大幅提升,ForEach-Object -Parallel这类并行能力也才有了实现基础。
版本号的读法很关键。7.x 的第一位是主版本,第二位是功能版本,第三位是补丁版本。发布通道一般分三类:长期支持版(LTS)、常规发布版、预览版(Preview)。长期支持版跟着 .NET 的 LTS 节奏走,生命周期长,适合生产环境和日常办公机器;常规发布版功能更新快,适合想尝鲜的开发者;预览版则是给要提前验证兼容性的人用的,接口随时可能变,不建议装在主力机上。
这里有个常被忽略的点:不同大版本依赖的 .NET 运行时不一样。7.4 系列基于 .NET 8,7.5 系列基于 .NET 9。MSI 和包管理器安装时会把对应运行时一起带上,但如果你是解压 zip 便携版,就得自己确认机器上有没有匹配的运行时,否则pwsh.exe双击就是一闪而过。我在一台老笔记本上就栽过这个跟头,解压完直接运行,窗口闪一下就没了,折腾了半小时才发现是缺运行时。
提示:装之前先确定你要的是长期支持版还是常规发布版。两者可以共存,但日常用建议只保留一个主版本,避免脚本在不同机器的默认
pwsh之间行为不一致。
1.2 为什么它能和系统自带的 5.1 并存
系统自带的 Windows PowerShell 5.1 装在C:\Windows\System32\WindowsPowerShell\v1.0下,这个目录被大量系统组件、管理工具、安装程序依赖,动它基本等于给自己找麻烦。PowerShell 7 的设计从一开始就考虑到了这点,采用的是**并行安装(side-by-side)**策略:独立目录、独立的可执行文件名、独立的模块路径、独立的配置文件路径。
具体来说,7 的默认安装目录是C:\Program Files\PowerShell\7,可执行文件是pwsh.exe;5.1 是powershell.exe。你在命令行里敲powershell打开的还是 5.1,敲pwsh打开的才是 7。两者的 profile 文件也不在同一处,7 的用户级 profile 在文档目录下的PowerShell文件夹里,5.1 的在WindowsPowerShell文件夹里。模块搜索路径同样分开,5.1 的模块不会自动出现在 7 里,反之亦然。
这种设计的价值在于迁移成本可控。你可以先在 7 里跑通新脚本,遇到老脚本依赖某个只支持 .NET Framework 的模块,随时切回 5.1 执行,两边互不干扰。但代价也要认清:这不是无缝过渡,有些基于 .NET Framework 的老模块在 7 里根本加载不了,需要找对应的新版本或者自己改写。
1.3 五种安装方式的取舍对比
网上的教程之所以让人看晕,很大原因是每个人用的安装方式不同。实际常用的就这么几种,各自的适用场景差别很明显:
| 安装方式 | 适用场景 | 优点 | 局限 |
|---|---|---|---|
| 系统包管理器 | 个人日常、批量部署 | 一条命令,升级卸载都方便 | 需要系统版本支持,源里版本可能滞后 |
| MSI 安装包 | 企业环境、需要精细控制 | 参数齐全,可静默、可定制右键菜单 | 包体较大,需手动下载 |
| ZIP 便携版 | 免安装、U 盘携带、多版本并存 | 解压即用,不写注册表 | 无自动升级,PATH 需手工配 |
| 脚本一键装 | 新机器快速初始化 | 省事 | 需要信任脚本来源,失败排查困难 |
| 系统包仓库(Linux) | 服务器环境 | 与系统更新体系统一 | 仓库配置有门槛 |
我个人的选择习惯是:自己办公机用包管理器,图省事;给团队做镜像或者要交付给别人用的机器,用 MSI 加静默参数,行为可预期;需要临时验证某个特定版本的行为,直接解压 zip 到临时目录,用完删目录就行,不留痕迹。
选择逻辑其实就一句话:你要的是"装一个长期使用的工具"还是"临时跑一个特定版本"。前者优先选能被统一管理的安装方式,后者选不污染系统的便携方式。搞清楚这一点,后面具体的命令才有意义。
2. 装前检查:三分钟排掉八成隐患
2.1 系统版本、架构与运行时确认
PowerShell 7 对系统版本有明确门槛,Windows 这边一般要求 Windows 10 1809 及以上,服务器版对应 2019 及以上。低于这个版本不是说绝对装不上,但会遇到各种奇怪的兼容问题,不建议硬来。架构方面,现在主流是 x64,ARM 设备要选 arm64 包,装错了虽然不一定立刻报错,但运行时会走模拟层,性能和部分原生模块都会受影响。
确认方式很简单,开一个 5.1 的窗口敲:
[System.Environment]::OSVersion.Version $env:PROCESSOR_ARCHITECTURE [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture头一条给系统版本号,第二条给进程架构,第三条给操作系统架构。之所以要两条都看,是因为在 ARM 机器上跑 x64 进程时,$env:PROCESSOR_ARCHITECTURE会显示 AMD64,容易误导。以第三条为准最稳妥。
运行时这块,如果你走 MSI 或包管理器,安装程序会处理依赖,基本不用操心。但如果机器上之前装过某个版本的 .NET 运行时,又手动清理过,可能出现版本注册信息残缺的情况,表现为安装到一半回滚。这种时候先去"应用和功能"里看看有没有异常的运行时条目,必要时修复或重装运行时再回来装 PowerShell。
注意:不要为了"干净"去手动删系统目录里的运行时文件夹。运行时的卸载必须走正规卸载流程,手工删目录会留下注册表项,后续安装会被判定为"已存在但损坏",卡在那里进退两难。
2.2 现有环境扫描:版本、PATH、执行策略
装之前先摸清现状,能省掉后面大量"为什么版本不对"的排查时间。三件事:现在有哪些版本、PATH 里有什么、执行策略是什么。
# 看当前会话版本 $PSVersionTable # 找机器上所有 pwsh 可执行文件 Get-Command pwsh -All | Select-Object Source, Version # 看 PATH 里跟 PowerShell 相关的项 $env:PATH -split ';' | Where-Object { $_ -match 'PowerShell' } # 看各作用域的执行策略 Get-ExecutionPolicy -List$PSVersionTable里重点看PSEdition,值是Core说明是 7,是Desktop说明是 5.1。如果 PATH 里出现了多个指向不同版本目录的条目,那就是隐患:命令解析按 PATH 顺序走,靠前的先命中,你以为打开的是新版,实际跑的是旧版。这种情况我见过不止一次,尤其是先装 zip 版后来又装 MSI 的机器,两个目录都在 PATH 里,结果pwsh -v显示的版本和预期对不上。
执行策略也顺便看一眼。5.1 时代很多人把策略改成了Unrestricted,这个设置是分作用域的,7 默认继承的是Restricted或RemoteSigned,脚本一跑就报"禁止运行脚本"。提前知道现状,装完直接按需设置,不用临时抓瞎。
2.3 权限、杀软与离线环境的处理
安装类操作基本都需要管理员权限。Windows 上右键"以管理员身份运行"是最省事的做法,但要注意:如果你是从网络位置或者压缩包里直接双击安装包,可能触发系统的"来自其他计算机的文件"标记,导致安装程序被拦截或者解压出问题。稳妥做法是先把安装包完整复制到本地磁盘再执行。
安全软件的干扰是安装失败的高发原因。某些实时防护会对安装程序的解压释放行为敏感,表现为安装进度条卡住、报 1603 错误、或者装完发现文件不全。判断方法很直接:看安全软件的拦截日志里有没有对应时间点的记录。如果有,临时把安装目录加进白名单再装,装完把白名单撤掉——不要图省事一直挂着,那等于给自己开了个长期口子。
离线环境要单独说。没有外网的机器,包管理器和在线脚本都用不了,只能用离线安装包。这里的关键是依赖完整:MSI 包本身自带运行时,可以直接用;zip 包不带运行时,得提前把对应版本的运行时离线包一起准备好。另外离线机器上通常没有配置模块仓库源,装完之后Install-Module会失败,这个在规划阶段就要想到,把常用模块也一并离线下载好。
3. Windows 上的三条安装路线实操
3.1 包管理器一条命令(推荐日常)
系统自带的包管理器是最省心的路径,前提是系统版本够新。先搜一下确认包标识,别硬记:
winget search powershell输出里会列出几个条目,注意区分正式版和预览版,标识里带Preview字样的就是预览通道。确认之后执行安装,把搜索到的标识填进去:
winget install --id <搜索到的包标识> --source winget如果你要指定某个具体版本,加--version参数;想装完立刻用新版本覆盖当前会话,加--silent走静默安装更干净。装完不需要重启,但已经打开的终端窗口不会自动生效,因为 PATH 是在进程启动时读取的。关掉重开一个窗口,敲pwsh -v验证。
升级同样是这条路径:
winget upgrade --id <包标识>这里有个实操细节值得说:包管理器安装的版本和源里同步存在时间差,源里更新晚几天是常态。急着用新版本的话,还是得走 MSI 或者直接下 zip。另外包管理器安装默认会写 PATH、注册文件关联和右键菜单,行为跟 MSI 基本一致,卸载时也是走同一套注册信息,比较规范。
提示:如果你的机器上装了多个包管理器(系统自带的、第三方的),尽量只用其中一个来管理 PowerShell,混用容易出现"一个认为装了、另一个认为没装"的尴尬局面,卸载时尤其麻烦。
3.2 MSI 安装包:图形与静默参数全解
MSI 是控制力最强的方式,适合需要精确控制安装行为的场景。图形化安装没什么好说的,下一步到底,但有几个勾选项值得停下来看一眼:
- 添加到 PATH:默认勾选。取消的话,装完必须用完整路径调用,一般不推荐取消。
- 启用 PowerShell 远程处理:会配置 WinRM 相关设置。只在需要远程管理的机器上勾,普通办公机勾上等于多开了一个服务面。
- 注册资源管理器右键菜单:装了之后在文件夹上右键能直接"在此处打开 PowerShell",挺方便,但有些企业的终端管理策略会把这个菜单项屏蔽掉。
- 文件右键"使用 PowerShell 运行":跑单个脚本时有用,但误点风险也高,看个人习惯。
真正体现价值的是静默安装参数。批量部署时用得上:
msiexec /i "PowerShell-7.x.x-win-x64.msi" /qn /norestart ADD_PATH=1 REGISTER_MANIFEST=1 ENABLE_PSREMOTING=0 ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1/qn是全静默,无任何界面;/norestart抑制自动重启;后面几个大写属性对应界面上的勾选项,1为启用,0为禁用。写部署脚本时把这些显式声明出来,比依赖默认值靠谱得多——默认值会随版本变化,显式声明才是可复现的。
安装日志建议打开,出问题时这是唯一的线索来源:
msiexec /i "PowerShell-7.x.x-win-x64.msi" /qn /l*v "%TEMP%\pwsh-install.log"日志文件动辄几 MB,别看全文,直接搜Return value 3,这是 MSI 标记失败动作的标准写法,往上下各看几十行就能定位到具体哪一步挂了。
3.3 ZIP 便携版:解压即用与 PATH 手工挂载
便携版适合三种人:没管理员权限的、需要多版本并存的、只想临时试一下的。流程是下载对应架构的 zip 包,解压到一个你记得住的目录,比如D:\Tools\pwsh-7,然后直接运行目录里的pwsh.exe。
想让它变成全局可用,得手工挂 PATH。用户级 PATH 不需要管理员权限:
$target = 'D:\Tools\pwsh-7' $userPath = [Environment]::GetEnvironmentVariable('PATH', 'User') if ($userPath -notlike "*$target*") { [Environment]::SetEnvironmentVariable('PATH', "$userPath;$target", 'User') }这段逻辑里加了个去重判断,因为重复执行会把同一条路径反复追加,PATH 越滚越长,早晚撞上长度限制。改完 PATH 必须重开终端。
便携版的坑主要集中在两点。第一是运行时依赖,前面提过,zip 包不带运行时,机器上没有匹配版本的话pwsh.exe直接闪退,用命令行启动能看到具体报错。第二是没有文件关联和右键菜单,.ps1文件双击还是用记事本打开,这是预期行为,不是装坏了。如果你确实需要这些集成,还是老老实实用 MSI。
多版本并存是便携版的杀手级用法。解压两三个不同版本的目录,分别起名pwsh-7.4、pwsh-7.5,验证脚本兼容性时直接调对应目录下的可执行文件,互不干扰,验证完删目录即可,系统里一点痕迹都不留。
3.4 装完必须跑的验证清单
装完不验证,等于没装。下面这几条一次跑完,能覆盖绝大多数安装异常:
# 1. 版本与版本类型 $PSVersionTable | Format-List # 2. 可执行文件位置,确认没跑到旧版本 Get-Command pwsh | Select-Object Source # 3. 模块路径是否指向新目录 $env:PSModulePath -split ';' # 4. 基础功能自检 Get-ChildItem $PSHOME | Measure-Object Get-Help Get-Process -Examples | Select-Object -First 5第一条里PSEdition必须是Core,Version是 7 开头。第二条确认路径指向你刚装的位置,如果是 zip 版的旧目录,说明 PATH 顺序有问题。第三条看模块路径里有没有新版本自己的 Modules 目录,没有的话后面装模块会找不到位置。第四条是功能性验证,Get-Help能出内容说明帮助文件完整,有些精简安装会漏掉帮助内容。
还有个容易被忽略的检查:文件签名。从非官方渠道拿到的安装包,装之前就该验一下:
Get-AuthenticodeSignature 'D:\Downloads\PowerShell-7.x.x-win-x64.msi' | Format-List Status, SignerCertificateStatus是Valid才继续。这条不是形式主义,命令行工具的运行权限很高,来源不明的包风险不小。
4. Linux 与 macOS 的安装路径
4.1 Linux:二进制包与发行版包管理器
Linux 上的安装逻辑跟 Windows 差别很大,核心是"解压到固定位置 + 建符号链接"。官方提供的是 tar.gz 二进制包,通用做法:
# 下载后解压到指定目录 sudo mkdir -p /opt/pwsh/7 sudo tar -xzf powershell-7.x.x-linux-x64.tar.gz -C /opt/pwsh/7 # 建符号链接,让 pwsh 全局可用 sudo ln -sf /opt/pwsh/7/pwsh /usr/bin/pwsh # 验证 pwsh -v符号链接这一步是关键。不建链接的话,每次都得敲完整路径,脚本里写 shebang 也没法用。用ln -sf里的-f是为了覆盖已有链接,升级时直接重跑这段就行,不用先删旧的。
发行版自己的包管理器也能装,通常是.deb或.rpm包。这种方式的好处是纳入系统包管理体系,升级卸载都跟其他软件一致;坏处是仓库里的版本往往比官方发布晚,而且不同发行版的打包方式有差异。跑长期服务的机器建议用这种方式,便于统一运维;开发机想用新特性,还是 tar.gz 直接解压更痛快。
依赖方面,Linux 上的 PowerShell 需要一些基础库,主流发行版基本都预装了。极简镜像(比如容器基础镜像)里可能缺,表现为启动时报找不到某个.so文件。这种时候用ldd看一下依赖树,缺什么补什么,别去猜。
4.2 macOS:包管理器与 pkg 两条路
macOS 上有两条主流路径。第一条是用第三方包管理器,命令简洁,升级卸载一条命令搞定:
brew install --cask powershell用 cask 是因为 PowerShell 提供的是应用形式的安装包,不是普通的命令行 formula。升级用brew upgrade --cask powershell,卸载用brew uninstall --cask powershell,这些都由包管理器接管,不用自己清残留。
第二条路是下载 pkg 安装包双击安装。这种方式会把文件装到/usr/local/下面,并在/usr/local/bin里建链接。适合不想装包管理器的机器,或者企业环境统一分发。卸载时不能只把应用拖进废纸篓,得走 pkg 的卸载流程,否则链接和配置文件都会留下。
Apple Silicon 和 Intel 芯片的包是分开的,下载时注意选对架构。装错了虽然能通过 Rosetta 转译运行,但启动速度明显变慢,而且某些依赖原生库的模块会加载失败。
4.3 跨平台安装后的统一验证
三个平台装完之后,验证的落脚点其实是同一套:
$PSVersionTable $PSHOME [System.Runtime.InteropServices.RuntimeInformation]::OSDescription$PSHOME给出安装根目录,Linux 上应该是/opt/pwsh/7之类,macOS 上是应用包里的路径。这个变量在写跨平台脚本时很有用——需要读取安装目录下的资源文件时,用它拼路径比硬编码安全得多。
跨平台场景还有个坑:默认编码和换行符。Windows 上默认可能是 UTF-16 或带 BOM 的 UTF-8,Linux/macOS 上是无 BOM 的 UTF-8。同一份脚本在两个平台跑,中文输出可能一个正常一个乱码。这不是安装问题,但装完跨平台环境后很快就会撞上,提前把脚本文件统一存成无 BOM 的 UTF-8 能省不少事。
5. 装完别急着用:四项必做配置
5.1 Profile 文件分层与路径
Profile 是 PowerShell 启动时自动执行的脚本,相当于命令行的"开机启动项"。它分好几个作用域,路径各不相同:
| 作用域 | 适用对象 | 典型用途 |
|---|---|---|
| CurrentUserCurrentHost | 当前用户 + 当前宿主 | 个人别名、提示符定制 |
| CurrentUserAllHosts | 当前用户 + 所有宿主 | 环境变量、函数库 |
| AllUsersCurrentHost | 所有用户 + 当前宿主 | 团队统一的宿主配置 |
| AllUsersAllHosts | 所有用户 + 所有宿主 | 机器级基础配置 |
查看实际路径用$PROFILE | Format-List *,一次列出全部四个。新手最常犯的错是把内容写进了AllUsersAllHosts,结果影响了机器上所有用户,包括服务账户,排查起来很费劲。个人配置一律写在CurrentUserAllHosts里,这个位置最不容易出事。
创建 profile 的正确姿势是先判断存在性再创建,不要直接覆盖:
if (-not (Test-Path $PROFILE.CurrentUserAllHosts)) { New-Item -ItemType File -Path $PROFILE.CurrentUserAllHosts -Force } notepad $PROFILE.CurrentUserAllHosts注意:profile 里不要放耗时操作,比如网络请求、大目录扫描。每次开终端都执行一遍,几秒钟的延迟积累起来很影响体验。需要预加载的数据放到按需调用的函数里。
5.2 PSReadLine 与命令行体验
从 5.1 换到 7 的人,第一感受往往是"补全变聪明了",这背后是 PSReadLine 模块。7 自带这个模块,但默认配置比较保守,几个开关打开后体验会明显不同:
Set-PSReadLineOption -PredictionSource History Set-PSReadLineOption -PredictionViewStyle ListView Set-PSReadLineOption -EditMode Windows Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete第一条启用基于历史记录的预测,输入时会灰显提示你之前敲过的完整命令,按右方向键直接采纳。第二条把预测结果改成列表展示,候选多的时候比单行提示清楚。第三条保持 Windows 的编辑习惯,习惯 Emacs 键位的可以改成Emacs。第四条把 Tab 改成菜单式补全,比默认的循环补全好用得多。
这几行写进 profile 就长期生效。不过要留意版本差异:不同版本的 PSReadLine 支持的参数不完全一样,某些新参数在老版本上会报"找不到参数"。写进 profile 前先在当前会话里逐条试一遍,能过再落盘,否则下次开终端直接一片红字。
5.3 执行策略、模块仓库与签名
执行策略是脚本能不能跑的总开关。7 默认比 5.1 严格,第一次跑.ps1很可能就撞上"禁止运行脚本"。改之前先想清楚范围:
# 只改当前用户,影响面最小 Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned # 确认各作用域现状 Get-ExecutionPolicy -ListRemoteSigned的含义是:本地写的脚本直接跑,从网络下载的脚本必须有有效签名。这个平衡点在日常使用中比较合适。改成Unrestricted或者Bypass确实什么都能跑,但也意味着任何来源的脚本都能在你机器上执行任意操作,风险自己掂量。
模块仓库这边,7 默认指向公共的模块库。装模块前先确认源配置:
Get-PSRepository Find-Module -Name PSReadLine Install-Module -Name <模块名> -Scope CurrentUser -Repository PSGallery-Scope CurrentUser装到用户目录,不需要管理员权限,也不会污染系统级目录。企业内网环境通常有自己的内部源,用Register-PSRepository注册后把默认源换掉,避免每次装模块都往外网跑。
签名验证这块,自己写的脚本如果要在团队内分发,建议加个自签名证书,不然每台机器都要单独改策略。用New-SelfSignedCertificate生成证书,Set-AuthenticodeSignature给脚本签名,再把证书导入到目标机器的受信任发布者存储里。流程稍长,但一次配好,后面分发省事。
5.4 终端与应用集成
新版 PowerShell 装完,很多人的终端里默认还是 5.1,得手动切。Windows Terminal 里的做法是打开设置,找到"启动"里的默认配置文件,把它改成 PowerShell 7 对应的那一项。改完新开的标签页就是 7 了。这一步不做,你会经常在"我以为我在用新版"和"怎么这个语法不支持"之间反复横跳。
右键菜单的集成情况取决于安装方式。MSI 安装时勾了对应选项才会有,便携版没有。想要的话可以手工加注册表项,但不建议新手折腾,改错了影响资源管理器稳定性。真需要频繁在某个目录下开终端,直接从终端里cd过去更简单。
还有个实用技巧是把常用目录做成快捷函数放进 profile:
function work { Set-Location 'D:\Projects\current' } function logs { Set-Location "$env:LOCALAPPDATA\Temp" }比记一长串路径靠谱,也比频繁用鼠标点目录快。
6. 卸载:比安装更容易留尾巴
6.1 卸载前的三项检查
卸载前先做三件事,能避免大部分"卸不干净"的问题。
第一,确认没有进程占用。开着的pwsh窗口、后台跑的脚本、被 VS Code 之类编辑器挂载的终端会话,都会锁住安装目录里的文件,导致卸载程序报"文件正在使用"。用Get-Process pwsh看一眼,全部关掉再动手。
第二,备份 profile。用户级 profile 文件默认不在安装目录里,卸载程序一般不会删,但有些清理工具会顺手带走。里面有你的别名、函数、环境变量设置,丢了重写很痛苦。直接复制一份到别的目录,几秒钟的事。
第三,记下安装方式和安装位置。这决定了你该用哪种卸载方法。查安装位置:
Get-Command pwsh -All | Select-Object Source, Version如果输出里只有一个路径,且在Program Files下,基本是 MSI 或包管理器装的;如果在你自己选的目录下,就是 zip 版;如果出现多个路径,说明装过不止一次,需要逐个处理。
6.2 Windows:包管理器、MSI 与 ZIP 三种卸载
包管理器装的,一条命令解决:
winget list --name PowerShell winget uninstall --id <包标识>先list确认标识和版本,再uninstall,别凭记忆敲标识,拼错了会提示找不到包,白折腾。
MSI 装的,优先走"应用和功能"里的卸载入口,行为最标准。命令行方式:
# 从注册表里找到产品码 Get-ItemProperty HKLM:\SOFTWARE\Classes\Installer\Products\* | Where-Object { $_.ProductName -like '*PowerShell*' } | Select-Object ProductName, PSChildName拿到产品码后用msiexec /x {产品码} /qn静默卸载。注意这里的产品码格式是紧凑的 GUID,跟常见的带大括号格式不一样,转换规则是把每 8 位一组倒序重排——嫌麻烦的话直接用安装包反向执行msiexec /x 安装包路径更省事。
ZIP 版的"卸载"本质就是删目录加清 PATH:
$target = 'D:\Tools\pwsh-7' Remove-Item $target -Recurse -Force $userPath = [Environment]::GetEnvironmentVariable('PATH', 'User') $newPath = ($userPath -split ';' | Where-Object { $_ -and $_ -ne $target }) -join ';' [Environment]::SetEnvironmentVariable('PATH', $newPath, 'User')删目录前务必确认$target变量指向正确。我见过有人变量写错,把整个 Tools 目录端了,里面还有其他工具。稳妥做法是先Get-ChildItem $target看一眼内容,确认是这个版本的安装目录再删。
6.3 Linux 与 macOS 的清理
Linux 上 tar.gz 装的,卸载就是反向操作:
sudo rm -rf /opt/pwsh/7 sudo rm -f /usr/bin/pwsh符号链接一定要单独删,只删目录的话/usr/bin/pwsh会变成一个悬空链接,之后敲pwsh报"没有那个文件或目录",看着像没删干净。用ls -l /usr/bin/pwsh确认链接已消失。
包管理器装的用对应命令卸载,deb 系是sudo apt remove <包名>,rpm 系是sudo dnf remove <包名>,把配置也一起清掉的话加--purge或--remove-purge之类的参数,具体看发行版。macOS 上 brew 装的用brew uninstall --cask powershell,pkg 装的用sudo pkgutil --forget <包标识>配合删除/usr/local/下的相关目录。
配置文件目录在各平台的位置不同,但都值得单独检查一遍:
# 用户级配置目录,卸载后可能残留 $env:LOCALAPPDATA $HOME/.config/powershell里面是历史记录、profile、模块缓存。想彻底清净就一起删,但删之前确认里面没有你还想保留的 profile 内容。
6.4 残留清单与卸载后验证
卸载完成后按下面这张清单逐项确认:
| 检查项 | 检查方式 | 正常状态 |
|---|---|---|
| 可执行文件 | Get-Command pwsh -All | 报错找不到命令 |
| PATH 变量 | $env:PATH -split ';' | 无相关目录 |
| 安装目录 | Test-Path 'C:\Program Files\PowerShell' | False |
| 用户配置目录 | Test-Path "$env:LOCALAPPDATA\PowerShell" | 按需保留或删除 |
| 右键菜单 | 文件夹上右键 | 无相关菜单项 |
| 文件关联 | 双击.ps1文件 | 不再关联到 pwsh |
| 计划任务/服务 | Get-ScheduledTask过滤 | 无残留条目 |
PATH 里残留是最常见的。卸载程序不一定能清干净,尤其是装过多个版本又手动改过 PATH 的机器。残留的危害不在于占地方,而在于你以后重装时,命令可能仍然解析到那个已经不存在的路径,报错信息还特别迷惑。
验证一句话搞定:开一个新终端,敲pwsh,应该是"无法将 pwsh 项识别为 cmdlet"这类报错。能打开就说明没卸干净,回去接着查。
7. 常见问题速查与排查思路
7.1 版本、路径类问题
装完敲pwsh提示找不到命令。九成是 PATH 没生效。先确认安装目录存在,再检查 PATH 里有没有对应条目,最后确认终端是新开的。如果 PATH 里明明有,命令还是找不到,用where.exe pwsh看系统实际解析到了哪里,有时候是另一个同名程序把位置占了。
敲pwsh -v显示的版本跟装的不一致。PATH 里有多个条目,靠前的那个是旧的。用Get-Command pwsh -All列出全部,把不需要的从 PATH 里剔掉,顺序也要调整到新版本在前。
脚本里的powershell调用跑的还是 5.1。这是预期行为,powershell.exe和pwsh.exe是两个不同的程序。老脚本里硬编码了powershell的,要么改脚本,要么加个包装函数做映射。批量改脚本时用正则替换,但改完必须逐个跑一遍,有些脚本依赖 5.1 特有的行为,硬迁过去会出问题。
7.2 安装失败类问题
MSI 安装报 1603。这是最泛化的错误码,含义是"安装过程中发生致命错误",本身不说明原因。必须看日志,搜Return value 3定位到具体动作。常见成因有三个:目录权限不足、旧版本残留导致状态冲突、安全软件拦截文件写入。按这个顺序排查,命中率最高。
报 2502/2503。这两个码跟 MSI 服务的权限上下文有关,典型出现在通过某些远程会话或者受限账户执行安装时。解决办法是把安装包放到本地磁盘,用管理员身份从命令行执行msiexec,不要在压缩包里直接双击。
安装进度卡在某个百分比不动。先别急着结束进程,给它几分钟。真卡死了就取消,清理临时目录后重来。反复卡在同一位置的,多半是安全软件在逐个扫描释放的文件,把安装目录加白名单再试。
装完提示缺少某个 DLL。运行时依赖没装全。MSI 一般不会出现,zip 版常见。去系统事件查看器里找应用错误日志,会明确写出缺哪个文件,装对应的运行时包即可。
7.3 启动与模块类问题
pwsh启动一闪而过。命令行里执行能看到具体报错:缺运行时、profile 里有语法错误、或者杀软把某个依赖文件隔离了。先加-NoProfile参数排除 profile 因素:
pwsh -NoProfile能正常启动就说明是 profile 的问题,逐段注释排查。
模块加载报"未能加载文件或程序集"。这是典型的 .NET Framework 模块在 7 上不兼容。用Get-Module -ListAvailable看模块的兼容性标记,PSEdition里没有Core的就是不支持的。解决办法是找该模块的新版本,或者改用 5.1 执行相关逻辑。
中文输出乱码。控制台代码页和脚本编码不一致。7 默认用 UTF-8,老脚本可能是 GBK 编码保存的。用Get-Content -Encoding显式指定读,或者把脚本文件另存为 UTF-8。终端本身也要设成 UTF-8 代码页,两者得对上。
7.4 卸载类问题
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 应用列表里找不到卸载项 | zip 版安装,未注册 | 直接删目录 + 清 PATH |
| 卸载报文件被占用 | 有 pwsh 进程或编辑器挂载 | 关进程,必要时重启 |
| 卸载后右键菜单还在 | 注册表项未清 | 手动删对应注册表键 |
| 卸载后重装失败 | 注册表残留产品信息 | 用官方清理工具或手工清注册表 |
| 卸载后 PATH 报错 | PATH 里有悬空路径 | 编辑 PATH 删掉无效项 |
| 卸载后 5.1 打不开 | 误删了系统组件 | 用系统文件检查工具修复 |
表格最后一条要特别提醒:5.1 的目录在系统目录下,手工删文件极容易误伤。清理时严格限定在你确认属于 7 的路径上,不要图省事整目录删除。
8. 几条踩坑心得
装和卸这件事,真正费时间的从来不是那几条命令,而是环境里那些看不见的历史包袱。我自己反复撞过的几件事,写下来给后来人省点功夫。
一是永远先摸清现状再动手。拿到一台机器,先跑一遍版本、PATH、执行策略的检查,比装完出问题再回头查快得多。尤其是接手的别人用过的机器,PATH 里可能躺着三四个历史版本路径,你以为的"全新安装"其实是"第四个版本"。
二是安装日志比搜索引擎有用。MSI 的/l*v日志、包管理器的详细输出、事件查看器里的应用错误,这三处基本能覆盖所有安装失败的原因。养成开日志的习惯,出问题时不用靠猜。
三是卸载比安装更值得做笔记。装的时候都是标准流程,卸的时候每个人机器上的残留都不一样。我自己维护了一个小清单,记录每台机器上 PowerShell 的安装方式、路径、特殊配置,换机器或者交接时直接照单清理,比现场摸索快十倍。
四是多版本共存不是坏事,但要管住默认值。开发和验证阶段留两三个版本很正常,关键是 PATH 顺序和默认终端配置要明确,别让自己都搞不清当前敲的命令跑的是哪一版。给每个版本的启动加个明显的提示符标记,比如在 profile 里把 prompt 加上版本号前缀,一眼就能分辨。