Windows PowerShell 5.1 与 PowerShell 7 的区别 ── 企业内部脚本迁移实务指南

· · PowerShell, Windows, 迁移, 自动化, 运维改善, 脚本, 现有资产利用

「在服务器上装了 PowerShell 7,现在的脚本不会坏掉吧?」「一直用 5.1 会不会有问题?」── 越来越多背负着企业内部运维脚本的客户向我们提出这类问题。Windows 出厂自带的 PowerShell(5.1),与需要另行安装的 PowerShell 7。由于名字相同,很容易被误解为「升级版本后就会被替换掉」,但实际情况是两者是并存的不同产品

如果没有正确理解这层关系就引入 7,往往会踩到两种坑中的一种:「装了却什么都没变(任务依旧跑在 5.1 上)」,或者反过来,「迁移之后日文文件对接出现了乱码」。尤其是后者是日文环境特有的事故,原因在于默认字符编码的差异。

本文面向拥有企业内部脚本的信息系统・运维负责人,从原理层面系统整理 5.1 与 7 的关系与差异,并附带判断表梳理实际推进迁移的步骤。

1. 先说结论

  • Windows PowerShell 5.1 与 PowerShell 7 是不同的产品,二者并行共存(side by side)。5.1 随 Windows 一同安装,运行在 .NET Framework 之上;7 是单独安装、构建在 .NET 之上的产品,即使安装了 7,5.1 也不会消失。12
  • 微软没有为 5.1 新增任何功能。5.1 的支持期限跟随 Windows 本体的生命周期,开发的主轴是 7。新编写的脚本应以 7 为基准。13
  • 可执行文件不同。5.1 是 powershell.exe,7 是 pwsh.exe。只要不改写任务计划程序等处的启动命令,现有机制就会继续在 5.1 下运行。45
  • 默认字符编码不同。5.1 因命令而异(Out-File 是 UTF-16LE、Get-Content 是 ANSI 等),7 统一使用不带 BOM 的 UTF-8。这是日文环境迁移时首先会踩到的地雷。6
  • 对于 7 中无法运行的模块,有 Windows 兼容功能可用。Import-Module -UseWindowsPowerShell 可以加载到后台的 5.1 进程,通过远程处理调用,但返回的是序列化后的对象,无法调用方法。7
  • #Requires -Version$PSVersionTable 在代码中明确「这个脚本该在哪个版本下运行」。这样可以在执行前就拦截「在意料之外的版本下运行、悄悄坏掉」这类事故。89
  • 迁移按照盘点→在 7 中执行测试→更新启动命令的分阶段方式推进。7 本身通过 MSI 或 winget 安装,更新的分发方式(是否走 Microsoft Update)也要在一开始就确定好。524

2. 5.1 与 7 是什么关系 ── 不是替换,而是共存

首先用表格把整体情况梳理清楚。

项目 Windows PowerShell 5.1 PowerShell 7
获取方式 随 Windows 一同安装1 需另行安装(MSI/winget 等)2
基础平台 .NET Framework 4.x5 .NET(7.4 基于 .NET 8.0 等)54
可执行文件 powershell.exe pwsh.exe4
安装位置 $Env:windir\System32\WindowsPowerShell\v1.05 $Env:ProgramFiles\PowerShell\75
今后的开发 不再新增功能1 开发的主轴,存在 LTS/Stable 版本发布3
支持期限 跟随 Windows 本体的生命周期3 跟随所依赖 .NET 的支持策略3

7 并不会取代 5.1,而是安装到不同的目录,以并行(side by side)的方式运行。模块存放位置(PSModulePath)、配置文件(profile)、事件日志都分别独立管理,由于 7 一侧的 PSModulePath 中也包含 5.1 的模块路径,因此从 7 中可以加载许多现有模块。52

「自己现在处于哪一侧」可以随时通过下面两行来确认。$PSVersionTable 是保存 PowerShell 版本信息的自动变量。9

# 确认自己当前所处的是哪一个 PowerShell
$PSVersionTable.PSVersion   # 5.1.x 则为 Windows PowerShell,7.x 则为 PowerShell 7
$PSVersionTable.PSEdition   # Desktop = Windows PowerShell / Core = PowerShell 7

官方的定位也十分明确。Windows PowerShell 是随 Windows 一同发布的版本,微软不再通过新增功能对其进行更新,支持期限与所使用的 Windows 版本挂钩。而另一边的 PowerShell(7 系列)构建在更新的 .NET 之上,每个发行版本都会按照所依赖 .NET 的支持策略确定各自的支持期限。13 5.1 不会在明天就消失,但从实务角度得出的结论是:「今后要新写的脚本」「今后要长期使用的脚本」应以 7 为基准。

3. 首先踩到的地雷 ── 默认编码差异与乱码

日文环境迁移中最常见的故障就是乱码。原因十分明确:两者的默认字符编码不同。6

操作 5.1 的默认值 7 的默认值
Out-File・重定向(>) UTF-16LE(带 BOM)6 不带 BOM 的 UTF-86
Set-Content / Add-Content ANSI(日文环境下为 Shift_JIS)6 不带 BOM 的 UTF-8
Get-Content(不带 BOM 的文件) ANSI6 不带 BOM 的 UTF-8
Export-Csv ASCII(日文字符会丢失)6 不带 BOM 的 UTF-8
脚本本身的解析(不带 BOM) ANSI 代码页6 UTF-8
# 即使是同一行代码,5.1 与 7 生成的文件字节序列也不同
'你好' | Out-File -FilePath C:\temp\hello.txt
# 在 5.1 中执行 → 生成带 BOM 的 UTF-16LE 文件
# 在 7 中执行   → 生成不带 BOM 的 UTF-8 文件

这在实务中意味着两件事。

第一,以 Shift_JIS 为前提的文件对接,一旦切换到 7 上,读和写都可能同时出现乱码。因为 5.1 的 Get-Content 会把不带 BOM 的文件当作 ANSI(日文环境下即 Shift_JIS)来读取,而 7 则会以 UTF-8 的方式读取。对策是在所有文件输入输出处都显式指定 -Encoding。在 7 中既可以用代码页编号(-Encoding 932)指定,也可以用注册名指定,7.4 以后还可以使用 ansi 这个取值。6 CSV 处理的具体写法,已经整理在同时发布的《用 PowerShell 自动化 Excel・CSV 业务处理》一文中。

第二,是脚本文件本身的保存格式。如果 5.1 读取一份以不带 BOM 的 UTF-8 格式保存、并包含日文注释的脚本,会将其误解析为 ANSI,从而导致乱码或语法错误。按照官方文档的建议,只要把包含非 ASCII 字符的脚本以带 BOM 的 UTF-8 格式保存,无论在 5.1 还是 7 中都能被正确解析。6

4. 兼容性 ── 哪些东西会失效,Windows 兼容功能又有多大能耐

4.1. 哪些内容会无法运行

7 能够原样加载许多现有模块5,但也有一些是加载不了的。以下是官方列出的代表性例子。

  • 已不再随附的模块: PSWorkflow/PSWorkflowUtility(工作流)、PSScheduledJob、ISE 专用模块、Microsoft.PowerShell.LocalAccounts 等模块,7 中不再包含。4
  • 管理单元(Snap-in): 早于模块出现的旧式扩展形式「管理单元」,7 不再支持。4
  • 深度依赖 .NET Framework 的代码: 由于 7 所依赖的 .NET 基础不同,直接调用 .NET 方法的脚本,其行为有可能发生变化。54
  • 细微的行为变化: Export-Csv 默认不再输出 #TYPE 行,Group-Object 返回的分组会被排序,诸如此类依赖输出内容的脚本会受到影响的变化还有不少。4

反方向的不兼容也同样存在。使用三元运算符、ForEach-Object -Parallel7 中新增的语法・功能编写的脚本,在 5.1 下无法运行5 因此需要针对每个脚本决定:是「写成两边都能运行」,还是「明确标注只在哪一边运行」。

微软自有模块的适配情况,可以在官方的模块兼容性页面上查阅。10

编辑环境(ISE)的迁移去向也要一并确定好。Windows PowerShell ISE 并没有从 Windows 中移除的计划,安全性以及优先级较高的修复也会持续提供,但新功能的开发已经终止,其只能对应 PowerShell 5.1 及更早版本11 也就是说,用 ISE 编写并运行打算跑在 7 上的脚本,这种做法并不成立。官方引导的迁移去向是 Visual Studio Code 加 PowerShell 扩展,安装扩展后可以在集成控制台中切换要使用的 PowerShell 版本(还可以在设置中追加更多路径)。针对习惯了 ISE 的用户,官方还准备了「在 VS Code 中重现 ISE 操作体验」的指南,从那里开始引导迁移会比较顺畅。11 信息系统现场中 ISE 用户往往很多,脚本迁移计划与编辑环境更换建议在同一时间一并告知。

4.2. Windows 兼容功能(-UseWindowsPowerShell)的机制与限制

7 中提供了 Windows 兼容功能,用于处理只能在 5.1 下运行的模块。

# 通过兼容功能加载一个不支持 7 的模块(官方文档中的示例)
Import-Module -Name ScheduledTasks -UseWindowsPowerShell

其机制是远程处理(Remoting)的一种应用。后台会启动一个 Windows PowerShell 5.1 进程,模块被加载到一个名为 WinPSCompatSession 的会话中,而 7 一侧则导入由隐式远程处理生成的代理模块。System32 下 5.1 专用的模块,即便只是按名称指定或依靠命令自动检测,也会隐式地通过这套机制被加载。7

画成图之后,两个进程之间的关系就一目了然了。

powershell.exe ── 后台启动的 5.1 进程pwsh.exe ── PowerShell 7 的进程转发命令调用结果只返回序列化后的值副本无法调用方法WinPSCompatSession由兼容功能加载的所有模块共享同一个 Runspace仅能在 5.1 下运行的模块本体脚本本体代理模块由隐式远程处理生成的入口,并非本体

如图所示,7 一侧存在的只是入口,而不是模块本体。实际情况并非「装了 7 就能全部跑在 7 上」,而是「从 7 拜托 5.1 去执行,再接收一份结果的副本」,后面提到的所有限制都源于这个结构。

这项功能很方便,但如果不理解其限制就使用,会在不知不觉中出问题。官方明确列出的限制如下。7

  • 来回传递的是序列化后的值,而不是原始对象。返回对象的方法无法调用,手头拿到的只是属性的快照。
  • 仅能在本地 Windows 上运行,且需要有 Windows PowerShell 5.1。
  • 通过兼容功能加载的所有模块,共享同一个 Runspace(同一个 5.1 进程)。
  • 部分模块(如 PSScheduledJob)默认会被拒绝加载。

诸如「调用取得结果的方法」「在管道中途需要用到原始对象」这类处理,通过兼容功能是无法实现的。这种情况下虽然也可以把整条管道都交给 5.1 一侧执行、只取回最终结果7,但从实务经验来看,与其把事情搞复杂,不如干脆把这部分处理原样留在 5.1 上更便于维护。

5. 防御性地编写脚本 ── #Requires 与版本分支

在迁移期间,必然会出现「不知道会在哪个版本下被执行」的状态。在意料之外的版本下运行、中途悄悄坏掉是最糟糕的情况,因此需要在脚本一侧加入防御。

写上 #Requires 语句后,如果不满足条件,PowerShell 会在执行之前就拒绝运行该脚本。8

#Requires -Version 7.0
# 该脚本仅限 7 专用(使用了 ForEach-Object -Parallel 等功能)。
# 若通过 powershell.exe(5.1)启动,从这里开始就完全不会被执行

反过来,仅限 5.1 使用的脚本要写上 #Requires -PSEdition DesktopDesktop 是 5.1 系列的版本名称,Core 是 7 系列的版本名称。89

如果一份两边都能运行的脚本,只想让部分行为有所区别,可以用 $PSVersionTable 在运行时进行分支。9

# 一份 5.1 与 7 两边都能运行的脚本,只对存在版本差异的部分做分支
if ($PSVersionTable.PSVersion.Major -ge 6) {
    $enc = 932            # 7: 可以用代码页编号指定 Shift_JIS
} else {
    $enc = 'Default'      # 5.1: Default = 系统的 ANSI 代码页
}
Get-Content -LiteralPath $path -Encoding $enc

要点在于,这类明确标注不是等到「迁移完成之后」才加,而是要在「盘点阶段」就加进去。只要有一行 #Requires,任何人都能立刻看出这份脚本属于哪个世界。

6. 迁移的推进方式 ── 从盘点到更新任务计划程序

实际的迁移按下面的顺序推进。一次性整体切换是事故的根源,因此分阶段迁移才是原则。

步骤 1: 盘点。从脚本存放位置与任务计划程序中,梳理出正在运行的 .ps1 及其启动命令。

# 从任务计划程序中梳理出启动了 PowerShell 的任务
Get-ScheduledTask | ForEach-Object {
    foreach ($action in $_.Actions) {
        # 为了同时捕捉到像 cmd.exe /c powershell ... 这样的间接启动,需要同时检查可执行文件与参数
        if ("$($action.Execute) $($action.Arguments)" -match 'powershell|pwsh') {
            [pscustomobject]@{
                TaskPath  = $_.TaskPath        # 任务名只在文件夹内唯一,因此也要记录路径
                TaskName  = $_.TaskName
                Execute   = $action.Execute    # 是 powershell.exe 还是 pwsh.exe
                Arguments = $action.Arguments
            }
        }
    }
} | Export-Csv -Path .\ps-tasks.csv -NoTypeInformation -Encoding UTF8

生成的 ps-tasks.csv 共有 4 列。下面列出各列的含义与格式示例(取值仅为示例,实际内容因环境而异)。

内容 取值示例
TaskPath 任务所在的文件夹。任务名只在文件夹内唯一 \\Contoso\Batch\
TaskName 任务名称 DailyReport
Execute 启动的可执行文件 powershell.exe / C:\Program Files\PowerShell\7\pwsh.exe / cmd.exe
Arguments 参数字符串 -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1

制作这份 CSV,是为了查看以下三点。Execute 为 powershell.exe 的行,是仍在 5.1 下运行的任务,也就是迁移对象。Execute 为 cmd.exe 的行,说明 PowerShell 的启动命令藏在 Arguments 里,需要打开确认具体内容。而Arguments 中既没有出现 -File 也没有出现 -Command 的行,说明是以位置参数的方式传入的调用方式,在步骤 5 中替换成 pwsh 时解释方式会发生变化(原因见步骤 5)。只要把这三类分门别类,迁移计划的分母就确定下来了。

步骤 2: 引入 7。通过 MSI 安装包(适合软件分发管理工具部署)或 winget 进行安装。52

选择安装哪个版本、如何安装,可以参考下面的标准来判断。32

论点 选项 判断标准
选哪个版本 LTS / Stable 业务服务器选 LTS。LTS 对应 .NET 的 LTS 版本,更新范围限定在重大安全修复与维护上,设计目标是把对现有工作负载的影响降到最低。Stable 包含新功能,但会在下一个 LTS 发布约 6 个月后停止支持3
客户端设备 winget 官方将其列为在 Windows 客户端上的推荐安装方式2
服务器・大规模部署 MSI 安装包 官方明确标注最适合 Windows Server 与企业部署。命令行属性还可以指定更新渠道2
MSIX(应用商店)版 需注意 是按用户安装的形式,无法面向所有用户安装,且应用沙箱会导致无法使用基于 WSMan 的 PowerShell Remoting 等限制。不适合用在服务器上2
# 用 winget 安装。更新同样通过 winget upgrade 走同一条渠道
winget install --id Microsoft.PowerShell --source winget

# 想用 MSI 安装包安装时(适合服务器・软件分发管理工具场景)
winget install --id Microsoft.PowerShell --source winget --installer-type wix

winget 本身也有前提条件。从 7.6.0 版本的 winget 软件包开始,winget install --id Microsoft.PowerShell 的行为变成了默认安装 MSIX 软件包,因此如果想要 MSI,需要像上面那样加上 --installer-type wix。另外,winget 在 Windows Server 2022 及更早版本上无法使用(Windows Server 2025 的桌面体验版随附)。面向服务器群组的部署,最好以 MSI 为前提来规划。2

更新运维方式也要提前确定好。7.2 及以后的 MSI 提供了通过 Microsoft Update 接收更新的选项(默认启用),可以纳入 WSUS 或配置管理工具的常规更新流程。4 最糟糕的模式,就是任由野生安装放置不管,导致老旧版本的 7 一直残留下去。

步骤 3: 在 7 中执行测试。对盘点出的每份脚本用 pwsh 执行,确认是否能正常运行、输出文件是否出现乱码。由于 7 与 5.1 是共存的,因此可以在不停止生产环境任务的情况下进行测试,这正是并行(side by side)设计带来的好处。2 如果出错,就按第 4 章的思路排查兼容性问题(模块、.NET API、行为变化)。

如果不先定好「运行成功」的标准,测试就没有终点,因此先把合格条件列成核对清单。

  • pwsh -NoProfile -File <脚本> 能顺利跑到最后,$LASTEXITCODE 以 0 结束
  • 错误流中没有任何输出(对于预期内的警告,需要确认内容后再予以放行)
  • 依赖模块都能在 7 中正常加载(Import-Module 能通过。也要留意是否落入了兼容功能)
  • 输出文件的内容与 5.1 版本一致(见下面的 Compare-Object)
  • 输出文件的编码符合接收方的预期(第 3 章。如果存在以 Shift_JIS 为前提的对接方,这一项是必检项)
  • 涉及变更的处理已用 -WhatIf 确认对象与 5.1 时相同
  • 执行时间没有出现异常增长(如果落入了兼容功能,有时会变慢)

比对输出内容,最可靠的做法是用同一份脚本分别在 5.1 与 7 中运行,然后取差异。

# 分别用 5.1 与 7 运行同一份脚本,比较输出文件
& "$Env:windir\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -File .\daily-report.ps1
Move-Item .\report.csv .\report-51.csv -Force
& "$Env:ProgramFiles\PowerShell\7\pwsh.exe" -NoProfile -File .\daily-report.ps1
Move-Item .\report.csv .\report-7.csv -Force

# 逐行比较差异。如果存在每次运行都会变化的列(比如执行时间),比较前应先去掉该列
Compare-Object (Get-Content .\report-51.csv) (Get-Content .\report-7.csv)

# 进一步比较字节是否完全一致(BOM 或换行符的差异会体现在这里)
(Get-FileHash .\report-51.csv).Hash -eq (Get-FileHash .\report-7.csv).Hash

出现差异时,首先要区分是「值本身不同」,还是「看起来一样但字节序列不同」。如果 Compare-Object 没有发现差异,只有 Get-FileHash 不一致,那原因就出在编码或换行符上(第 3 章)。请把「迁移完成」定义为「产出与 5.1 时相同的成果物」,而不是「在 7 中不出异常地跑完」。

步骤 4: 明确标注该在哪个版本运行。对通过测试的脚本补写上 #Requires -Version 7.0,对要留在 5.1 上的脚本补写上 #Requires -PSEdition Desktop(第 5 章)。

步骤 5: 更新启动命令。改写任务计划程序的操作(Action)。如果忘了这一步,就会发生「本以为已经迁移到了 7,实际却一直在 5.1 下运行」的情况。

# 变更前(在 5.1 下执行):
#   powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1
# 变更后(在 7 下执行):
#   "C:\Program Files\PowerShell\7\pwsh.exe" -NoProfile -File C:\scripts\daily-report.ps1

需要注意的是,pwsh.exe 的第一个位置参数已经从 -Command 变成了 -File。如果机械地替换相当于 powershell.exe -Command "..." 的调用方式,解释方式会发生变化,因此请务必显式指定 -File / -Command4

执行策略与脚本签名的处理方式,请参见同时发布的《PowerShell 的执行策略与脚本签名》;批处理文件(.bat)的迁移判断,请参见《这个批处理文件,应该迁移到 PowerShell 吗?》。

7. 实务定式(判断表)

论点 选项 判断标准
新脚本的基准 5.1 / 7 原则上选 7。5.1 处于不再新增功能的维持现状状态,开发主轴是 713
现有脚本的迁移 一次性整体切换 / 分阶段迁移 盘点→在 7 中测试→从通过测试的脚本开始更新启动命令。正因为是并行共存,才能分阶段迁移5
存在 5.1 专用模块 放弃迁移 / -UseWindowsPowerShell / 仅让该处理留在 5.1 上 使用兼容功能前提是理解其序列化限制(无法调用方法)。如果情况复杂,让该部分留在 5.1 上反而更易维护7
版本的明确标注 不做任何处理 / #Requires 为所有脚本加上 #Requires 或运行时检查。在执行前拦截意料之外版本下的运行8
文件输入输出 交给默认设置 / 显式指定 -Encoding 始终显式指定。从结构上防止因 5.1 与 7 默认值不同而产生的乱码6
7 的更新运维 手动重新安装 / MSI 的 Microsoft Update 联动或 winget 先确定更新渠道再分发。被放置不管的旧版 7 最为危险42

8. 总结

  • 5.1 与 7 是不同的产品,二者并行共存。安装 7 不会破坏现有机制,但反过来说,只要不改变启动命令,也就不会有任何东西被迁移。
  • 5.1 处于不再新增功能・支持期限跟随 Windows 本体的维持现状模式,7 才是开发的主轴。新脚本应以 7 为基准编写。
  • 日文环境中最大的地雷是默认编码的差异(5.1 因命令而异,7 统一为不带 BOM 的 UTF-8)。通过在输入输出处显式指定 -Encoding,以及把脚本以带 BOM 的 UTF-8 保存来防范。
  • 在 7 中无法运行的模块,可以借助 Windows 兼容功能来救场,但存在只能返回序列化值这一限制。如果实在无法解决,就让该处理单独留在 5.1 上。
  • 用 #Requires 与 $PSVersionTable 在代码中明确标注「这份脚本该在哪个版本下运行」,从而拦截意料之外版本下的执行。
  • 迁移按照盘点→引入 7(MSI/winget)→执行测试→补写 #Requires→更新任务计划程序启动命令的分阶段方式推进。

相关文章

相关咨询领域

合同会社小村软件承接企业内部脚本资产的盘点,以及向 PowerShell 7 分阶段迁移的规划与实施、依赖 5.1 专用模块的处理的切分、「迁移之后出现乱码・无法运行了」这类故障的调查。

参考链接

  1. Microsoft Learn, What is Windows PowerShell?。关于 Windows PowerShell 与 PowerShell 是不同的产品、Windows PowerShell 随 Windows 一同安装并构建在 .NET Framework 之上、最新版本为 5.1、微软已不再通过新增功能进行更新、支持期限与所使用的 Windows 版本挂钩等内容。  2 3 4 5 6

  2. Microsoft Learn, Install PowerShell 7 on Windows。关于 PowerShell 7 不会取代 Windows PowerShell 5.1、而是安装到新的目录中并行运行、默认安装位置为 $Env:ProgramFiles\PowerShell\7、winget・MSI 等安装方式等内容。  2 3 4 5 6 7 8 9 10 11 12

  3. Microsoft Learn, PowerShell Support Lifecycle。关于 PowerShell 7 存在 LTS 与 Stable 两种发布类型、支持结束日期跟随所依赖 .NET 的支持策略、Windows PowerShell 作为 Windows 的组件跟随 Windows 的支持生命周期等内容。  2 3 4 5 6 7 8

  4. Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x。关于可执行文件名从 powershell.exe 变为 pwsh.exe 从而支撑起并行共存、第一个位置参数从 -Command 变为 -File、PSWorkflow・PSScheduledJob・LocalAccounts 等模块及管理单元不再包含在 7 中、Export-Csv 默认省略 #TYPE 行与 Group-Object 输出已排序结果等行为变化、各版本所依赖的 .NET 基础、7.2 及以后 MSI 的 Microsoft Update 联动选项等内容。  2 3 4 5 6 7 8 9 10 11

  5. Microsoft Learn, Migrating from Windows PowerShell 5.1 to PowerShell 7。关于 PowerShell 7 的设计前提是与 5.1 并行共存(不同的安装路径・PSModulePath・配置文件・事件日志)、5.1 与 7 各自的安装位置、许多现有模块能够在 7 中运行以及 UseWindowsPowerShell 可以弥补兼容性、三元运算符与 ForEach-Object -Parallel 等新功能、通过 MSI/ZIP 进行部署等内容。  2 3 4 5 6 7 8 9 10 11 12

  6. Microsoft Learn, about_Character_Encoding。关于 Windows PowerShell 5.1 的默认编码因命令而不一致(Out-File 与重定向为 UTF-16LE,Set-Content/Get-Content 为 ANSI,Export-Csv 为 ASCII 等)、PowerShell 6 及以后统一以不带 BOM 的 UTF-8 为默认值、5.1 会把不带 BOM 的脚本误解析为 ANSI 因此包含非 ASCII 字符的脚本应以带 BOM 的 UTF-8 保存、代码页编号指定与 7.4 的 ansi 取值等内容。  2 3 4 5 6 7 8 9 10 11

  7. Microsoft Learn, about_Windows_PowerShell_Compatibility。关于兼容功能会把模块加载到后台的 Windows PowerShell 5.1 进程(WinPSCompatSession)中、并通过隐式远程处理生成代理模块这一机制、UseWindowsPowerShell 的显式加载与自动加载两种方式、基于序列化值运行而非原始对象・仅限本地 Windows・共享单一 Runspace・默认拒绝加载列表等限制等内容。  2 3 4 5

  8. Microsoft Learn, about_Requires。关于 #Requires 语句会在不满足指定的 PowerShell 版本(-Version)、版本类型(-PSEdition Core 或 Desktop)、模块等前提条件时直接拒绝脚本的执行本身等内容。  2 3 4

  9. Microsoft Learn, about_Automatic_Variables。关于 $PSVersionTable 是保存当前会话 PowerShell 版本详情的只读哈希表、PSEdition 属性在 5.1(完整功能版 Windows)中取值 Desktop、在 6 及以后取值 Core 等内容。  2 3 4

  10. Microsoft Learn, PowerShell 7 module compatibility。关于该页面汇总了微软各模块(包括 Windows 管理相关模块)对 PowerShell 7 的适配情况等内容。 

  11. Microsoft Learn, Using Visual Studio Code for PowerShell Development。关于 Windows PowerShell ISE 虽然会保留在 Windows 中,但新功能开发已经终止、仅能对应 PowerShell 5.1 及更早版本、没有从 Windows 中移除的计划且会持续提供安全性与优先级较高的修复、PowerShell 开发应使用 Visual Studio Code 与 PowerShell 扩展、可以在会话菜单中切换所使用的 PowerShell 并额外设置路径、官方准备了在 VS Code 中重现 ISE 操作体验的指南等内容。  2

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

常见问题

汇总了咨询这一主题时常见的问题。

Windows PowerShell 5.1 与 PowerShell 7 有什么区别?
两者是不同的产品。5.1 随 Windows 一同安装,运行在 .NET Framework 之上,微软已经停止为其新增功能,支持期限跟随 Windows 本体的生命周期。7 是运行在 .NET(旧称 .NET Core)之上、需要单独安装的产品,是当前开发的主轴。7 并不会取代 5.1,而是安装到不同的目录,与 5.1 并行共存(side by side),可执行文件名也分别为 powershell.exe 与 pwsh.exe,加以区分。
安装 PowerShell 7 之后,现有的 5.1 脚本会不会坏掉?
不会坏掉。7 会安装到不同的目录(默认为 Program Files\PowerShell\7),模块存放位置与配置文件(profile)也都与 5.1 分开管理。任务计划程序等原本通过 powershell.exe 启动的既有机制,会一如既往地继续在 5.1 下运行。正因如此,反而要注意「仅仅安装了 7 并不代表已经完成任何迁移」这一点 ── 想让脚本跑在 7 上,必须显式地把启动命令切换为 pwsh.exe。
为什么在 PowerShell 7 中运行以前的脚本会出现乱码?
原因在于默认字符编码发生了变化。5.1 的默认编码因命令而异(例如 Out-File 是 UTF-16LE、Get-Content 是 ANSI 等),而 7 统一使用不带 BOM 的 UTF-8。由于日文环境中大量文件对接都以 Shift_JIS 为前提,如果保持默认设置直接迁移,读写两端都可能出现乱码。基本可以通过两点来防止:在文件输入输出时显式指定 -Encoding;把包含非 ASCII 字符的脚本本身以带 BOM 的 UTF-8 格式保存。
在 PowerShell 7 中无法运行的模块该怎么办?
首先确认在 7 中用普通的 Import-Module 是否能正常加载运行。如果无法运行,可以使用 Windows 兼容功能(Import-Module -UseWindowsPowerShell),它会把模块加载到后台的 5.1 进程中,再通过远程处理(Remoting)从 7 端调用。不过这种方式存在限制:返回的是序列化后的对象,无法调用方法;且只能在本地 Windows 上运行。遇到会触碰这些限制的处理,现实的做法是不必勉强,只让那部分处理继续留在 5.1 上运行。
企业内部脚本从 5.1 迁移到 7 应该怎样推进?
不要一次性全部切换,而应采用分阶段迁移。首先从任务计划程序与脚本存放位置中盘点出所有 .ps1,逐一用 7(pwsh)执行测试,确认是否能够正常运行。对于运行正常的脚本,补写上 #Requires -Version 7,并把任务计划程序的启动命令从 powershell.exe 更新为 pwsh.exe。只能在 5.1 下运行的脚本不要勉强迁移,而是明确标注应该用哪个版本运行后予以保留。7 本身可以通过 MSI 或 winget 安装,同时也要一并确定好更新的分发方式。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表