30 秒看懂
Microsoft PowerShell 工程经理 Steve Lee 讨论从 Windows PowerShell 5.1 转向开源、跨平台 PowerShell Core 以及当时即将推出的 PowerShell 7。他演示了错误处理、语言语法、并行处理、命令补全和 Windows 模块兼容性的变化。 在广泛的问答中,Lee 讨论模块管理、启动性能、SSH 远程操作、治理和 Azure Functions。发布日期、支持期限和未来计划均以演讲当时的情况为准。
- 1Windows PowerShell 5.1 继续受支持Lee 将 5.1 描述为功能完整的版本,关键维护仍会继续;新工作负载可以并行使用其他版本。
- 2PowerShell 7 与兼容性该版本定位为 PowerShell Core 6 之后的下一步,采用 .NET Core 3.1,并重新推进 Windows 模块兼容工作。
- 3错误处理简洁错误视图减少噪声,而 Get-Error 提供包括堆栈跟踪在内的更丰富诊断信息。
- 4并行处理有成本ForEach-Object -Parallel 可以帮助处理等待或核心未充分利用的工作,但线程和 runspace 会带来开销。
- 5Windows PowerShell 兼容性不受支持的 Windows 模块可以通过 Windows PowerShell 子进程运行;返回对象跨越远程边界后会被反序列化。
- 6SSH 远程操作通过 SSH 的 PowerShell remoting 支持跨平台并传输对象,但当时缺少 WinRM 的部分能力,例如 Just Enough Administration。
要点建议
- Windows PowerShell 5.1 被视为稳定且继续受支持的产品,新功能开发则转向跨平台 PowerShell。
- PowerShell 7 希望借助 .NET Core 3.1 和 Windows PowerShell 兼容进程改善 Windows 兼容性。
- 简洁错误和 Get-Error 为交互用户与开发者提供不同层次的细节。
- 并行执行有开销,应测量它是否有利于具体工作负载,而不是处处使用。
- 兼容性远程调用返回反序列化对象,它们不会保留远程对象的任意方法。
- 实验性功能可以用于测试,但其设计在稳定之前可能发生变化。
按章节阅读整理后的全文
从 Windows PowerShell 到开源
Lee 介绍 Windows PowerShell 5.1 的维护,以及转向 .NET Core、开源和多平台的过程。他回顾 PowerShell Core 6 的兼容性及发布自动化工作。
我在 Microsoft 管理 PowerShell 工程团队。演讲时团队有 11 名工程师,与几位项目经理合作;我们负责 shell、gallery、编辑器服务、Pester、PowerShellGet 和 OpenSSH。Windows PowerShell 的维护已移交给另一个 Windows 团队。
Windows PowerShell 5.1 是 Windows PowerShell 系列的最后一个版本,不计划在这个名称下推出 5.2、6 或 7。它仍是 Windows 的一部分,并继续获得关键修复,但 PowerShell Core 和 PowerShell 7 的新工作不计划回移。
可以把 5.1 看作功能完整且稳定的版本。如果现有业务工作负载运行正常,我认为没有必要仅为迁移而迁移。需要新功能的新自动化任务可以并行安装并使用另一个版本。
2016 年,我们宣布 PowerShell 将开源并支持跨平台。从 Windows .NET Framework 转向 .NET Core,使 shell 可以在 Windows 之外运行,同时也让社区能够贡献代码和修复。
开放代码也意味着重新考虑测试。许多现有 Windows 测试使用专有框架,而且重复很多,因此团队用 Pester 编写了新的开源测试,而不是简单地公开旧测试套件。
PowerShell Core 6.1 的重点是兼容 Windows PowerShell。工程师与 Windows 团队合作,验证并更新系统内置模块;Lee 估计,在这项工作中,许多模块的兼容程度达到约 60%–70%。
在 6.2 中,团队投入自动化,并将持续集成统一到 Azure DevOps。跨 Windows 和多个 Linux 发行版测试的成本很高。这项工作让一次典型预览版发布从三名工程师耗时约五个日历日,缩短到出现问题时约一名半工程师耗时两天。
PowerShell 7 计划与支持
他介绍当时计划的发布与支持节奏,并解释为何 Windows 当时不会内置 PowerShell 7。必要时,Windows PowerShell 兼容功能会使用独立进程。
PowerShell 7 的名称去掉了 Core。Lee 认为它在概念上是 Core 6 的下一步,而非一次全面破坏兼容性的重新设计:团队希望用户把它看作 PowerShell,而不是以为 Core 意味着功能缩水的子集。
目标是让它成为日常使用中 Windows PowerShell 的可行替代品。.NET Core 3.1 恢复了早期 .NET Core 缺少的许多 API,使兼容 .NET Framework 模块更可行。团队还恢复了部分命令,并与 Windows 团队合作处理内置模块。
演讲时,最终预览版已经发布,候选发布版即将推出,正式发布目标定在一月。团队正从开发分支挑选特定改动纳入发布,而不是自动接收所有改动。这些是当时的计划,并非当前发布时间表。
Lee 表示,PowerShell 7 计划作为与 .NET Core 3.1 对齐的长期服务版本,提供大约三年的安全和关键修复支持。PowerShell Core 6.2 遵循此前的生命周期,预计在新版本发布后退出支持。
团队计划每年发布,并让隔代长期支持版本与 .NET 对齐,其中包括设想基于 .NET 5 的 7.1 和基于 .NET 6 的 7.2。这些计划明确可能变化;团队也不打算仅为匹配 .NET 而提高 PowerShell 的主版本号。
当时没有计划将 PowerShell 7 内置于 Windows。障碍在于支持期限:.NET Core 的三年长期服务期短于 Windows 生命周期。Lee 指出,在一些企业中,即使安装 Microsoft 签名的软件也可能很困难。
对于没有标记为兼容 PowerShell Core 的 Windows 模块,预览版增加了一条兼容路径。PowerShell 7 可以利用作业基础设施,在 Windows PowerShell 进程中调用命令,而不要求启用 WinRM。
错误、Web 请求与语言功能
演示对比简洁错误和详细诊断,并展示 Web 请求处理。随后 Lee 演示空值相关运算符和三元运算符。
演示中首先看到的是简洁错误视图。旧式错误可能用大量信息占满屏幕,让许多用户感到困惑。新的默认视图突出直接的错误消息,用户仍可选择旧视图。

需要深入调查时,Get-Error 会显示更丰富的信息,包括 .NET 和 PowerShell 脚本堆栈跟踪。在包含多个错误的脚本中,简洁视图还会显示相关行,并用颜色帮助浏览。
云工作负载经常涉及 REST API 和 JSON。Lee 展示一个 HTTP 失败案例,并解释脚本可能需要响应正文、状态或标头来决定如何处理。如果每个失败的 HTTP 状态都变成终止性的 PowerShell 错误,处理起来可能很别扭。
社区贡献的一个选项允许 Invoke-WebRequest 和 Invoke-RestMethod 不再把失败的 HTTP 状态转换成 PowerShell 错误。脚本可以捕获状态码和响应标头,自己处理响应。
团队从社区高票请求中选择了几项语言功能。演示之一是空条件成员和索引访问:只有值非空时才尝试相应操作,避免为这种情况单独写一次检查。
该语法要求用大括号括住变量,因为 PowerShell 已经允许变量名中出现问号。这样可以避免破坏现有名称。Lee 提醒,省去一次空值检查并不能防止脚本中其他无关的错误。
空值合并运算符可以在值为空时提供默认值。在 Lee 的例子中,未设置的用户值可以回退到另一个值;如果已设置,则表达式返回原值。相关的赋值形式只在变量为空时更新它。
三元运算符根据条件从两个表达式中选择一个。其他语言的用户对它很熟悉,它也是热门请求,但 Lee 强调这是一种可选写法,不要求每个脚本都使用。
交互改进与实验性功能
Unix 文件元数据、补全、调试和高亮搜索结果都得到改进。Lee 区分了实验性设计与未经测试的实现。
在类 Unix 系统上,文件列表增加了原生长格式列表中常见的信息,包括用户和组。这些信息来自原生 API,在相应平台的 PowerShell Get-ChildItem 输出中显示。
交互式补全也得到改进。用户不必输入无效的偏好值、再从错误中查看可接受的枚举值,而是可以用 Tab 补全。Lee 尝试了另一个现场例子,但演示时没有成功写出正确语法。
一种新的操作偏好设置可以在发生错误时进入命令行调试器,而不必在每个位置显式加入调试器等待。这样更容易在运行过程中调查包含多个错误的脚本。
Select-String 可以突出显示匹配文本。结果仍是可用于自动化的对象,也可以关闭高亮。PowerShell 正增加更多可配置颜色,以便在交互式输出中区分项目及其内容。
Lee 区分了实验性功能与有 bug 的功能。预览版曾默认启用实验性功能以收集反馈;候选发布版将默认关闭它们。实验性意味着设计仍可能变化,用户不应把它当作稳定的生产接口依赖。
当时计划将简洁错误、三元运算符和空值合并稳定下来,而空条件成员和方法访问仍保持实验性。实验性功能仍可启用测试,但其设计变化不会被视为破坏性变更。
DSC、空值与并行执行
Lee 讨论调用 DSC 资源、数据库 null 和字符串分割。他演示并行迭代,并解释开销和并发限制。
团队还开发了 Invoke-DscResource,尽管 Desired State Configuration 本身属于另一个团队。思路是直接调用 DSC 资源的 test、set 或 get 操作,不要求系统上有本地配置管理器,Linux 和 macOS 也包括在内。
针对数据库用户,演示讨论了脚本如何比较缺失值和数据库 null。社区请求这一行为,希望减少常见比较中单独处理 DBNull 的需要。类似的便利也适用于空字符串。
字符串分割时使用负数计数会改变分割方向。正数可以从左向右分割,负数则从右侧开始,让用户更容易保留需要的部分,而不必进行额外处理。
ForEach-Object -Parallel 回应了 PowerShell Workflow 用户的常见请求:提供方便的并发执行方式。一个使用 sleep 的演示显示,多次迭代可以并行推进,而不是逐个等待完成。

Parallel 不是通用的加速开关。启动线程和 runspace 有成本,小任务反而可能变慢。对于等待网络请求或未充分利用 CPU 核心的工作,它更有希望带来收益;可以用 Measure-Command 判断具体工作负载是否真的更快。
ForEach-Object 本身创建本地 runspace。循环中的脚本仍可在远程会话上调用命令,但 parallel 参数本身不是远程计算机选择器。演讲中展示的默认并发限制为 5,用户可以按工作负载调整。
命令与 Windows 兼容性
临时驱动器和命令缩写方便交互使用。恢复的命令和兼容进程帮助 Windows 用户迁移现有脚本。
新的 Temp 驱动器映射到操作系统的临时目录,为 Windows 和类 Unix 系统提供便捷路径。它不同于 Pester 的 TestDrive,不会自动清理文件;它只是一个快捷入口,清理仍由用户负责。
交互式缩写展开有助于输入较长的命令名。输入命令的大写字母并使用 Tab 补全,就可以展开完整名称。这只用于交互补全;脚本运行时不会展开缩写,而完整名称也更易读。
PowerShell Core 6 中缺失的几个命令在版本 7 回归。剪贴板命令就是一个例子:早期 .NET Core 缺少的依赖曾阻止它们发布。这里讨论的跨平台实现只处理文本,不包括 Windows PowerShell 支持的文件剪贴板行为。
其他恢复的 Windows 命令包括性能计数器、回收站处理、打印和修补程序检查。一些命令仍不可用,其中部分依赖非公开 API。Lee 指出,较新的事件命令取代了一些旧的事件日志命令。
Out-GridView 提供交互式表格,可以筛选对象并将选中项继续传入管道。例如,脚本可以让用户选择服务,再由另一个命令处理所选服务。Lee 提醒,不要在例子中随意使用具有破坏性的后续操作。
.NET 桌面组件回归也让 Windows 脚本可以使用 WPF 和 WinForms。这个 .NET Core 版本中的 WPF 仅限 Windows;Lee 提到 Avalonia 是可能的跨平台替代方案,而不是声称 WPF 本身能在所有平台运行。
ServerManager 模块展示了兼容性问题。在此前的 PowerShell Core 示例中,它依赖不受支持的程序集,因此无法直接加载。PowerShell 7 可以启动 Windows PowerShell 子进程,在那里加载该模块。
PowerShell 7 中暴露的命令是代理函数,通过作业基础设施与子进程通信。检查或修改 Windows 功能等基本操作可以工作,但输出跨越远程边界后,格式可能不同。
返回的是反序列化对象,而不是原进程中的活动对象。本地可以访问其数据,但远程类型的方法未必能在副本上调用。判断现有脚本能否通过兼容模式工作时,这是一个重要限制。
问答:模块与性能
问题涉及操作系统检查、PowerShellGet v3 计划和性能。Lee 将脚本运行速度与启动延迟分开讨论。
对于需要跨操作系统运行的脚本,Lee 建议检查环境,或用 Get-Command 测试命令是否存在。当时,一些仅限 Windows 的命令可能在以后实现跨平台;另一些依赖平台特定 API,需要更多工作。
模块作者也需要检查依赖。不同 Linux 发行版未必具备相同的原生命令,因此运行时检查和有意义的错误消息会有帮助。Gallery 标签可以声明支持的操作系统,但 Lee 说当时的包工具尚未强制执行所有这些约束。
对于 PowerShellGet v3,Lee 希望简化安装。现有流程可能需要额外开关来处理命令名冲突、发布者差异或已经安装的版本。他的目标是让普通的模块安装请求更容易完成。
另一项拟议改动是采用 NuGet 风格的版本范围。依赖可以指定包含版本 3、但不包含版本 4,而不必用一长串 9 之类的人造最大版本。Lee 还讨论了直接使用 NuGet 包这一期望场景。
拟议中的重写将摆脱对 PackageManagement 的依赖,转向 C# 实现,提供更方便的用户体验和本地缓存。缓存可以加快搜索,也可能帮助识别缺失命令由哪个模块提供。当时预览版的时间仍未确定。
关于性能,Lee 预计许多脚本会从 .NET Core 和 PowerShell 优化中受益,但没有给出通用的加速数字。启动速度是另一回事:他预计在同一 Windows 系统上,PowerShell 7 的启动会慢于 Windows PowerShell 5.1。
他认为部分启动差异来自运行时准备本机代码的方式。Windows PowerShell 可以使用从托管程序集生成的本机映像,而这里使用的 .NET Core 方法不会预编译所有内容。团队计划继续优化启动,但他不预计马上达到同等速度。
Lee 在没有配置文件数据的情况下给出粗略估计,具体结果取决于系统:Windows PowerShell 或许需要 300–400 毫秒,PowerShell 7 或许需要 600–800 毫秒。这是演讲中的非正式估计,不是基准测试,也不是对当前版本的断言。
团队已经接手维护 PSReadLine,并计划在编辑器扩展中纳入较新版本。当时的目标是在 PowerShell 7 发布前后推出 PSReadLine 2.0,并为 Windows PowerShell 提供更新。
问答:远程操作、治理与 Azure
Lee 比较 SSH 与 WinRM 远程操作,并讨论旧版 Windows 的兼容性。他还回答社区 RFC 和 Azure Functions 中的 PowerShell 支持问题。
对于跨平台远程操作,Lee 推荐通过 SSH 使用 PowerShell remoting。这不只是通过 SSH 启动交互式 shell:PowerShell 远程协议会把对象传回客户端。SSH 跨平台工作,而基于 WinRM 的路径在 Linux 和 macOS 上存在限制。
当时,非 Windows WSMan 支持所依赖的开源基础设施存在缺口,使一些身份验证和 Exchange Online 场景变得困难。Lee 表示团队打算投入 SSH,并提到通过反向隧道进行远程调试的可能性。
一个限制是 Just Enough Administration,它可以约束远程用户在端点上能做什么。在 Lee 描述的场景中,它可以通过 Windows/WinRM 路径工作,却无法通过 SSH remoting 工作。添加类似支持是一个困难的未来项目。
Windows OpenSSH 在受支持的较新 Windows 版本上已可用于生产,但一个小团队仍需合并上游改动并将其集成到 Windows。Lee 提到 Azure 扩展是另一种安装方式,同时承认支持旧系统需要投入。
Active Directory 模块的兼容性取决于 Windows 版本。在较新的 Windows 版本中,更新使模块能够直接与 PowerShell Core 配合;在较旧系统中,Lee 介绍了 Windows PowerShell 兼容路径,但同样受反序列化对象的限制。
谈到有争议的改动时,Lee 提到有关语言功能的辩论。一些贡献者担心增加语法会提高复杂度,因为现有 if 语句已经能表达相同行为;另一些人则重视这些受欢迎的选项。委员会需要在不同观点之间权衡。
团队还在讨论如何让治理更加开放,可能让更多社区成员参与,并区分技术和战略职责。Lee 强调,演讲时尚未确定最终结构。
社区 RFC 审查出现积压,部分原因是小型委员会的会议时间有限,并优先处理了自己的提案。团队希望采用更轻量、更包容的流程,例如在贡献者投入完整 RFC 之前先在 issue 中讨论想法。
最后,Lee 谈到 Azure Functions。PowerShell 团队成员帮助构建了语言工作进程,使体验更贴近 PowerShell 脚本作者;公开预览之后,团队把所有权移交给 Azure Functions 团队。他希望该团队在 PowerShell 7 正式发布前后采用它,但没有承诺日期。
同频道的其他文章
1:34:29EN → 简体中文
1:34:36EN → 简体中文
15:48EN → 简体中文
1:48:21EN
1:20:57EN → 简体中文
1:12:58EN → 简体中文