Windows PowerShell 5.1 和 PowerShell 7.x 之间的差异

Windows PowerShell 5.1 基于 .NET Framework v4.5 构建。 随着 PowerShell 6.0 的发布,PowerShell 成为基于 .NET Core 2.0 构建的开源项目。 从 .NET Framework 迁移到 .NET Core 允许 PowerShell 成为跨平台解决方案。 PowerShell 在 Windows、macOS 和 Linux 上运行。

在 PowerShell 语言方面,Windows PowerShell 和 PowerShell 之间几乎没有差异。 最显著的差异在于 Windows 和非 Windows 平台之间的 PowerShell cmdlet 的可用性和行为,以及源于 .NET Framework 和 .NET Core 之间的差异的更改。

本文总结了 Windows PowerShell 和当前版本的 PowerShell 之间的显著差异和重大更改。 此摘要不包括已添加的新功能或 cmdlet。 本文也没有讨论版本之间的更改。 本文的目的是介绍 PowerShell 的当前状态,以及它与 Windows PowerShell 的区别。 有关版本与新增功能之间的更改的详细讨论,请参阅每个版本的 新增功能 文章。

.NET Framework 与 .NET Core

Linux 和 macOS 上的 PowerShell 使用 .NET core,这是 Microsoft Windows 上完整 .NET Framework 的子集。 这很重要,因为 PowerShell 提供对基础框架类型和方法的直接访问。 因此,由于框架的差异,在 Windows 上运行的脚本可能不会在非 Windows 平台上运行。 有关 .NET Core 中的更改的详细信息,请参阅 从 .NET Framework 迁移到 .NET Core的重大更改。

每个新版本的 PowerShell 都是基于较新版本的 .NET 构建的。 .NET 中可能存在影响 PowerShell 的重大更改。

  • PowerShell 7.5 - 基于 .NET 9.0 构建
  • PowerShell 7.4 - 基于 .NET 8.0 构建
  • PowerShell 7.3 - 基于 .NET 7.0 构建
  • PowerShell 7.2 (LTS-current) - 基于 .NET 6.0 构建(LTS-current)
  • PowerShell 7.1 - 基于 .NET 5.0 构建
  • PowerShell 7.0 (LTS) - 基于 .NET Core 3.1 (LTS) 构建
  • PowerShell 6.2 - 基于 .NET Core 2.1 构建
  • PowerShell 6.1 - 基于 .NET Core 2.1 构建
  • PowerShell 6.0 - 基于 .NET Core 2.0 构建

随着 .NET Standard 2.0的出现,PowerShell 无需修改即可加载许多传统的 Windows PowerShell 模块。 此外,PowerShell 7 还包括一项 Windows PowerShell 兼容性功能,允许你使用仍需要完整框架的 Windows PowerShell 模块。

有关详细信息,请参阅:

请注意 .NET 方法更改

虽然 .NET 方法更改并不特定于 PowerShell,但它们可能会影响脚本,尤其是在直接调用 .NET 方法时。 此外,构造函数可能会有新的重载。 这可能会影响如何使用 New-Object[type]::new() 方法创建对象。

例如,.NET 向 .NET Framework 4.5 中不可用的 [System.String]::Split() 方法添加了重载。 以下列表显示了 Windows PowerShell 5.1 中提供的 Split() 方法的重载:

PS> "".Split

OverloadDefinitions
-------------------
string[] Split(Params char[] separator)
string[] Split(char[] separator, int count)
string[] Split(char[] separator, System.StringSplitOptions options)
string[] Split(char[] separator, int count, System.StringSplitOptions options)
string[] Split(string[] separator, System.StringSplitOptions options)
string[] Split(string[] separator, int count, System.StringSplitOptions options)

以下列表显示了 PowerShell 7 中提供的 Split() 方法的重载:

"".Split

OverloadDefinitions
-------------------
string[] Split(char separator, System.StringSplitOptions options)
string[] Split(char separator, int count, System.StringSplitOptions options)
string[] Split(Params char[] separator)
string[] Split(char[] separator, int count)
string[] Split(char[] separator, System.StringSplitOptions options)
string[] Split(char[] separator, int count, System.StringSplitOptions options)
string[] Split(string separator, System.StringSplitOptions options)
string[] Split(string separator, int count, System.StringSplitOptions options)
string[] Split(string[] separator, System.StringSplitOptions options)
string[] Split(string[] separator, int count, System.StringSplitOptions options)

在 Windows PowerShell 5.1 中,可以将字符数组(char[])作为 string传递给 Split() 方法。 该方法在数组中出现任何字符时拆分目标字符串。 以下命令拆分 Windows PowerShell 5.1 中的目标字符串,但不拆分在 PowerShell 7 中:

# PowerShell 7 example
"1111p2222q3333".Split('pq')
1111p2222q3333

若要绑定到正确的重载,则必须将字符串类型转换为字符数组:

# PowerShell 7 example
"1111p2222q3333".Split([char[]]'pq')
1111
2222
3333

模块不再与 PowerShell 一起提供

出于各种兼容性原因,PowerShell 中不再包含以下模块。

  • ISE
  • Microsoft.PowerShell.LocalAccounts
  • Microsoft.PowerShell.ODataUtils
  • Microsoft.PowerShell.Operation.Validation
  • PSScheduledJob
  • PSWorkflow
  • PSWorkflowUtility

PowerShell 工作流

PowerShell 工作流 是 Windows PowerShell 中的一项功能,它基于 Windows Workflow Foundation (WF) 构建,可为长时间运行或并行化的任务创建可靠的 Runbook。

由于在 .NET Core 中缺少对 Windows Workflow Foundation 的支持,我们从 PowerShell 中删除了 PowerShell 工作流。

将来,我们希望在 PowerShell 语言中启用本机并行/并发,而无需 PowerShell 工作流。

如果需要在 OS 重启后使用检查点恢复脚本,我们建议使用任务计划程序在 OS 启动时运行脚本,但脚本需要维护自己的状态(如将其保存到文件)。

从 PowerShell 中删除的 cmdlet

对于 PowerShell 中包含的模块,出于各种兼容性原因或使用不受支持的 API,从 PowerShell 中删除了以下 cmdlet。

CimCmdlets

  • Export-BinaryMiLog

Microsoft.PowerShell.Core

  • Add-PSSnapin
  • Export-Console
  • Get-PSSnapin
  • Remove-PSSnapin
  • Resume-Job
  • Suspend-Job

Microsoft.PowerShell.Diagnostics

  • Export-Counter
  • Import-Counter

Microsoft.PowerShell.Management

  • Add-Computer
  • Checkpoint-Computer
  • Clear-EventLog
  • Complete-Transaction
  • Disable-ComputerRestore
  • Enable-ComputerRestore
  • Get-ComputerRestorePoint
  • Get-ControlPanelItem
  • Get-EventLog
  • Get-Transaction
  • Get-WmiObject
  • Invoke-WmiMethod
  • Limit-EventLog
  • New-EventLog
  • New-WebServiceProxy
  • Register-WmiEvent
  • Remove-Computer
  • Remove-EventLog
  • Remove-WmiObject
  • Reset-ComputerMachinePassword
  • Restore-Computer
  • Set-WmiInstance
  • Show-ControlPanelItem
  • Show-EventLog
  • Start-Transaction
  • Test-ComputerSecureChannel
  • Undo-Transaction
  • Use-Transaction
  • Write-EventLog

Microsoft.PowerShell.Utility

  • Convert-String
  • ConvertFrom-String

PSDesiredStateConfiguration

  • Disable-DscDebug
  • Enable-DscDebug
  • Get-DscConfiguration
  • Get-DscConfigurationStatus
  • Get-DscLocalConfigurationManager
  • Publish-DscConfiguration
  • Remove-DscConfigurationDocument
  • Restore-DscConfiguration
  • Set-DscLocalConfigurationManager
  • Start-DscConfiguration
  • Stop-DscConfiguration
  • Test-DscConfiguration
  • Update-DscConfiguration

WMI v1 cmdlet

以下 WMI v1 cmdlet 已从 PowerShell 中删除:

  • Register-WmiEvent
  • Set-WmiInstance
  • Invoke-WmiMethod
  • Get-WmiObject
  • Remove-WmiObject

CimCmdlet 模块 (aka WMI v2) cmdlet 执行相同的功能,并提供新功能和重新设计的语法。

删除了 New-WebServiceProxy cmdlet

.NET Core 不支持提供使用 SOAP 协议的服务的 Windows 通信框架。 此 cmdlet 已删除,因为它需要 SOAP。

*-Transaction cmdlet 已删除

这些 cmdlet 的使用非常有限。 决定停止支持他们。

  • Complete-Transaction
  • Get-Transaction
  • Start-Transaction
  • Undo-Transaction
  • Use-Transaction

*-EventLog cmdlet

由于使用了不支持的 API,*-EventLog cmdlet 已从 PowerShell 中删除。 Get-WinEventNew-WinEvent 可用于在 Windows 上获取和创建事件。

使用 Windows Presentation Framework (WPF) 的 cmdlet

.NET Core 3.1 添加了对 WPF 的支持,因此 PowerShell 7.0 的发布还原了以下特定于 Windows 的功能:

  • Show-Command cmdlet
  • Out-GridView cmdlet
  • Get-HelpShowWindow 参数

PowerShell Desired State Configuration (DSC) 更改

Invoke-DscResource 已还原为 PowerShell 7.0 中的实验功能。

从 PowerShell 7.2 开始,PSDesiredStateConfiguration 模块已从 PowerShell 中删除,并已发布到 PowerShell 库。 有关详细信息,请参阅 PowerShell 团队博客中的 公告

PowerShell 可执行文件更改

已将 powershell.exe 重命名为 pwsh.exe

PowerShell 的二进制名称已从 powershell(.exe) 更改为 pwsh(.exe)。 此更改为用户提供了一种确定性的方式,用于在计算机上运行 PowerShell,并支持 Windows PowerShell 和 PowerShell 的并行安装。

powershell.exe 重命名为 pwsh(.exe) 后的其他更改:

  • 将第一个位置参数从 -Command 更改为 -File。 此更改修复了 #!(亦称为 shebang)在非 Windows 平台上非 PowerShell shell 内执行的 PowerShell 脚本 中的使用问题。 这也意味着可以在不指定 -File的情况下运行命令,例如 pwsh foo.ps1pwsh fooScript。 但是,此更改要求在尝试运行 pwsh.exe -Command Get-Command等命令时显式指定 -c-Command
  • pwsh 接受 -i(或 -Interactive)切换表示交互式 shell。 这允许在 Unix 平台上将 PowerShell 用作默认 shell。
  • pwsh.exe中删除了参数 -ImportSystemModules-PSConsoleFile
  • 更改了 pwsh -Version,并调整了 pwsh.exe 的内置帮助,使其与其他原生工具保持一致。
  • -File-Command 的无效参数错误消息和与 Unix 标准一致的退出代码
  • 在 Windows 上添加了 -WindowStyle 参数。 同样,非 Windows 平台上基于包的安装更新是就地更新。

缩短的名称也与非 Windows 平台上 shell 的命名一致。

支持使用布尔参数运行 PowerShell 脚本

以前,使用 pwsh.exe 通过 -File 执行 PowerShell 脚本时,没有办法将 $true/$false 作为参数值传递。 添加了对 $true/$false 作为参数分析值的支持。 还支持 Switch 值。

改进了与 Windows PowerShell 的向后兼容性

对于 Windows,添加了一个新的开关参数 UseWindowsPowerShellImport-Module。 此开关在 PowerShell 7 中创建一个代理模块,该模块使用本地 Windows PowerShell 进程隐式运行该模块中包含的任何 cmdlet。 有关详细信息,请参阅 Import-Module

有关哪些Microsoft模块适用于 PowerShell 7.0 的详细信息,请参阅 模块兼容性表

针对 Windows 的 Microsoft 更新支持

PowerShell 7.2 添加了对 Microsoft Update 的支持。 启用此功能时,你将在传统的 Windows 更新(WU)管理流中获取最新的 PowerShell 7 更新,无论是使用适用于企业的 Windows 更新、WSUS、SCCM 还是“设置”中的交互式 WU 对话框。

PowerShell 7.2 MSI 包包含以下命令行选项:

  • USE_MU - 此属性有两个可能的值:
    • 1 (默认值) - 选择通过 Microsoft 更新或 WSUS 进行更新
    • 0 - 不要选择通过 Microsoft 更新或 WSUS 进行更新
  • ENABLE_MU
    • 1(默认)- 选择使用 Microsoft 更新、自动更新或 Windows 更新
    • 0 - 请勿选择使用 Microsoft 更新、自动更新或 Windows 更新

发动机变更

支持 PowerShell 作为默认 Unix shell

在 Unix 上,对于交互式 shell 而言,shell 通常会接受 -i,许多工具都期待这一行为(例如,script,以及在将 PowerShell 设置为默认 shell 时),并使用 -i 开关来调用 shell。 此更改具有突破性,因为 -i 以前可用作速记以匹配 -InputFormat,它现在需要使用 -in

自定义管理单元

PowerShell 管理单元是 PowerShell 社区中未广泛采用的 PowerShell 模块的前身。

由于支持管理单元的复杂性及其在社区中的使用不足,我们不再支持 PowerShell 中的自定义管理单元。

实验性功能标志

PowerShell 6.2 启用了对 实验功能的支持。 这样,PowerShell 开发人员就可以提供新功能,并在设计完成之前获取反馈。 这样,我们就避免在设计发展时做出重大更改。

使用 Get-ExperimentalFeature 获取可用实验性功能的列表。 可以使用 Enable-ExperimentalFeatureDisable-ExperimentalFeature启用或禁用这些功能。

在尝试从 GAC 加载之前,先从模块基路径加载程序集

以前,当二进制模块在 GAC 中具有模块程序集时,我们在尝试从模块基路径加载程序集之前从 GAC 加载该程序集。

对具有值类型元素类型的集合,跳过 null 元素检查

对于 Mandatory 参数和 ValidateNotNullValidateNotNullOrEmpty 属性,如果集合的元素类型是值类型,请跳过 null 元素检查。

保留 ParenExpressionSubExpressionArrayExpression$?

此 PR 更改了子管道 (...)、子表达式 $(...) 和数组表达式 @() 的编译方式,以便 $? 不会自动为 true。 相反,$? 的值取决于执行的管道或语句的结果。

当本机命令写入 stderr 时,将 $? 修复为非 $false

当本机命令写入 stderr 时,$? 不会设置时为 $false。 通常情况下,本机命令会写入 stderr 且不会指示失败。 仅当本机命令包含非零的退出代码时,$? 才会设置为 $false

使 $ErrorActionPreference 不会影响本机命令的 stderr 输出

本地命令通常会写入 stderr,但并非是故意表示失败。 通过此更改,stderr 输出仍捕获到 ErrorRecord 对象中,但如果 ErrorRecord 来自本机命令,运行时将不再应用 $ErrorActionPreference

更改 $OutputEncoding 以使用 UTF-8 NoBOM 编码,而不是 ASCII

在某些情况下,以前的编码 ASCII(7 位)将导致输出错误更改。 将 UTF-8 NoBOM 设置为默认值以保留 Unicode 输出,并且大多数工具和操作系统都支持该编码。

将带有参数 -Encoding 的 cmdlet 统一为 System.Text.Encoding 类型

-EncodingByte 已从文件系统提供程序 cmdlet 中删除。 新的参数 -AsByteStream现在用于指定输入是否需要字节流或输出是否为字节流。

New-ModuleManifest 编码更改为非 Windows 平台上的 UTF8NoBOM

以前,New-ModuleManifest 使用 BOM 在 UTF-16 中创建 psd1 清单,从而为 Linux 工具创建问题。 此重大变更将非 Windows 平台中 New-ModuleManifest 的编码更改为 UTF 编码格式(无 BOM)。

从大多数默认别名中删除 AllScope

为了加快范围创建速度,AllScope 已从大多数默认别名中删除。 为一些常用别名保留了AllScope,以便更快地查找。

-Verbose-Debug 不再替代 $ErrorActionPreference

以前,如果指定了 -Verbose-Debug,它会覆盖 $ErrorActionPreference的行为。 通过此更改,-Verbose-Debug 不再影响 $ErrorActionPreference的行为。

此外,-Debug 参数将 $DebugPreference 设置为 Continue,而不是 Inquire

使 $PSCulture 一致地反映会话中区域性更改

在 Windows PowerShell 中,将缓存当前区域性值,这样可避免值在会话启动后区域性发生变化时与之同步。 PowerShell 核心中修复了此缓存行为。

允许显式指定的命名参数取代展开的哈希表中的同一个参数

进行此更改后,展开中的命名参数将移到参数列表的末尾,这样在所有显式指定的命名参数被绑定后,它们就会被绑定。 找不到指定的命名参数时,简单函数的参数绑定不会引发错误。 未知的命名参数被绑定到简单函数的 $args 参数上。 将散点移到参数列表的末尾会更改参数在 $args中显示的顺序。

例如:

function SimpleTest {
    param(
        $Name,
        $Path
    )
    "Name: $Name; Path: $Path; Args: $args"
}

在前面的行为中,MyPath 不绑定到 -Path,因为它是参数列表中的第三个参数。 ## 因此它最终和 Blah = "World" 一起填充到“$args”中

PS> $hash = @{ Name = "Hello"; Blah = "World" }
PS> SimpleTest @hash "MyPath"
Name: Hello; Path: ; Args: -Blah: World MyPath

通过此更改,@hash 中的参数将移动到参数列表的末尾。 MyPath 成为列表中的第一个参数,因此它绑定到 -Path

PS> SimpleTest @hash "MyPath"
Name: Hello; Path: MyPath; Args: -Blah: World

语言更改

Null 合并操作符 ??

如果 null 合并运算符 ?? 不为 null,则它返回其左操作数的值。 否则,它将计算右操作数并返回其结果。 如果左侧操作数的计算结果为非 null,则 ?? 运算符不会计算其右侧操作数。

$x = $null
$x ?? 100
100

在下面的示例中,不会计算右操作数。

[string] $todaysDate = '1/10/2020'
$todaysDate ?? (Get-Date).ToShortDateString()
1/10/2020

Null 合并赋值运算符 ??=

仅当左操作数的计算结果为 NULL 时,Null 合并赋值运算符 ??= 才会将其右操作数的值赋值给其左操作数。 如果左侧操作数的计算结果为非 null,则 ??= 运算符不会计算其右侧操作数。

$x = $null
$x ??= 100
$x
100

在下面的示例中,不会计算右操作数。

[string] $todaysDate = '1/10/2020'
$todaysDate ??= (Get-Date).ToShortDateString()
1/10/2020

Null 条件运算符

注释

此功能已从实验性迁移到 PowerShell 7.1 中的主流。

仅当操作数的计算结果为非 NULL 时,NULL 条件运算符才对其操作数应用成员访问 ?. 或元素访问 ?[] 操作;否则,它会返回 NULL。

由于 PowerShell 允许 ? 成为变量名称的一部分,因此使用这些运算符需要对变量名称进行正式规范。 因此,在变量名称(如 ${a})或 ? 是变量名称 ${a?}的一部分时,需要使用 {}

在以下示例中,将返回 PropName 的值。

$a = @{ PropName = 100 }
${a}?.PropName
100

以下示例将返回 null,而不尝试访问成员名称 PropName

$a = $null
${a}?.PropName

同样,将返回元素的值。

$a = 1..10
${a}?[0]
1

当操作数为 null 时,不访问该元素,并返回 null。

$a = $null
${a}?[0]

注释

不应将 ${<name>} 的变量名称语法与 $() 子表达式运算符混淆。 有关详细信息,请参阅 about_Variables的“变量名称”部分。

添加 & 运算符用于作业控制

& 置于管道末尾会导致管道作为 PowerShell 作业运行。 管道在后台运行时会返回作业对象。 当管道作为任务运行时,可以使用所有标准 *-Job cmdlet 来管理该任务。 此管道中使用的变量(特定于进程的变量除外)自动复制到该作业,从而使 Copy-Item $foo $bar & 正常运行。 作业也会在当前目录中运行,而不是用户的主目录。

PSCustomObject 上的新方法/属性

我们已将新方法和属性添加到 PSCustomObjectPSCustomObject 现在包括与其他对象一样 Count/Length 属性。

$PSCustomObject = [pscustomobject]@{foo = 1}

$PSCustomObject.Length
1
$PSCustomObject.Count
1

这项工作还包括 ForEachWhere 方法,可用于对 PSCustomObject 项进行操作和筛选。

$PSCustomObject.ForEach({$_.foo + 1})
2
$PSCustomObject.Where({$_.foo -gt 0})
foo
---
  1

从 PSMethod 到委托的转换

可以将 PSMethod 转换为委托。 这样,就可以将 PSMethod[M]::DoubleStrLen 作为委托值传递到 [M]::AggregateString

class M {
    static [int] DoubleStrLen([string] $value) { return 2 * $value.Length }

    static [long] AggregateString([string[]] $values, [Func[string, int]] $selector) {
        [long] $res = 0
        foreach($s in $values){
            $res += $selector.Invoke($s)
        }
        return $res
    }
}

[M]::AggregateString((gci).Name, [M]::DoubleStrLen)

PowerShell 7.1 中的字符串比较行为已更改

PowerShell 7.1 基于 .NET 5.0 构建,引入了以下重大更改:

从 .NET 5.0 开始,区域性固定的字符串比较将忽略非打印控制字符。

例如,以下两个字符串被视为相同的:

# Escape sequence "`a" is Ctrl-G or [char]7
'Food' -eq "Foo`ad"
True

新 cmdlet

新 Get-Uptime cmdlet

Get-Uptime cmdlet 返回自操作系统上次启动以来经过的时间。 该 cmdlet 已在 PowerShell 6.0 中引入。

新 Remove-Alias cmdlet

Remove-Alias cmdlet 从当前 PowerShell 会话中删除别名。 该 cmdlet 已在 PowerShell 6.0 中引入。

新的命令行工具 Remove-Service

Remove-Service cmdlet 删除注册表和服务数据库中的 Windows 服务。 PowerShell 6.0 中引入了 Remove-Service cmdlet。

新 Markdown cmdlet

Markdown 是创建具有基本格式的可读纯文本文档(可呈现为 HTML)的标准。

PowerShell 6.1 中添加了以下 cmdlet:

  • ConvertFrom-Markdown - 将字符串或文件的内容转换为 MarkdownInfo 对象。
  • Get-MarkdownOption - 返回用于在控制台中呈现 Markdown 内容的当前颜色和样式。
  • Set-MarkdownOption - 设置用于在控制台中呈现 Markdown 内容的颜色和样式。
  • Show-Markdown - 在控制台中或以 HTML 格式显示 Markdown 内容

新 Test-Json cmdlet

Test-Json cmdlet 测试字符串是否为有效的 JavaScript 对象表示法(JSON)文档,并且可以选择性地根据提供的架构验证 JSON 文档。

PowerShell 6.1 中引入了此 cmdlet

支持实验性功能的新 cmdlet

PowerShell 6.2 中添加了以下 cmdlet 以支持实验功能。

新 Join-String cmdlet

Join-String cmdlet 将管道中的对象合并为单个字符串。 此 cmdlet 已在 PowerShell 6.2 中添加。

新视图 ConciseView 和 cmdlet Get-Error

PowerShell 7.0 具有新的默认视图 ConciseView,它增强了错误消息的显示,进而提高了交互式错误和脚本错误的可读性。 视图可通过首选项变量 $ErrorView进行用户选择。

使用 ConciseView时,如果错误不是来自脚本或分析器错误,则为单行错误消息:

Get-ChildItem -Path C:\NotReal
Get-ChildItem: Cannot find path 'C:\NotReal' because it does not exist

如果在脚本执行期间发生错误或分析错误,PowerShell 将返回一条多行错误消息,其中包含错误、指针和一条错误消息,其中显示了错误所在行。 如果终端不支持 ANSI 颜色转义序列(VT100),则不显示颜色。

PowerShell 7 中的默认视图 简明视图。 之前的默认视图是 NormalView,您可以通过设置首选项变量 $ErrorView来选择此视图。

$ErrorView = 'NormalView' # Sets the error view to NormalView
$ErrorView = 'ConciseView' # Sets the error view to ConciseView

注释

$Host.PrivateData 添加新属性 ErrorAccentColor,以支持更改错误消息的主题色。

如果需要,新的 Get-Errorcmdlet 提供了完全限定错误的完整详细视图。 默认情况下,cmdlet 显示上次发生的错误的完整详细信息,包括内部异常。

Get-Error cmdlet 使用内置变量 $Error 支持来自管道的输入。 Get-Error 显示所有管道错误。

$Error | Get-Error

Get-Error cmdlet 支持 最新 参数,允许你指定希望显示多少当前会话中的错误。

Get-Error -Newest 3 # Displays the lst three errors that occurred in the session

有关详细信息,请参阅 Get-Error

Cmdlet 更改

添加到 ForEach-Object 的并行执行

从 PowerShell 7.0 开始,遍历集合中项的 ForEach-Object cmdlet 现在由于新的 Parallel 参数而具备内置并行处理能力。

默认情况下,并行脚本块使用启动并行任务的调用方当前工作目录。

此示例从本地 Windows 计算机上的 5 个系统日志检索 50,000 个日志条目:

$logNames = 'Security','Application','System','Windows PowerShell','Microsoft-Windows-Store/Operational'

$logEntries = $logNames | ForEach-Object -Parallel {
    Get-WinEvent -LogName $_ -MaxEvents 10000
} -ThrottleLimit 5

$logEntries.Count

50000

Parallel 参数指定为每个输入日志名称并行运行的脚本块。

新的 ThrottleLimit 参数限制在给定时间并行运行的脚本块数。 默认值为 5。

使用 $_ 变量表示脚本块中的当前输入对象。 使用 Using: 范围修饰符将变量引用传递给正在运行的脚本块。

有关详细信息,请参阅 ForEach-Object

在 Windows 上检查 system32 以获取兼容的内置模块

在 Windows 10 1809 更新和 Windows Server 2019 中,我们更新了许多内置 PowerShell 模块,以将它们标记为与 PowerShell 兼容。

PowerShell 启动时,它会自动将 $windir\System32 作为 PSModulePath 环境变量的一部分包含在内。 但是,如果模块 CompatiblePSEdition 被标记为与 Core 兼容,则它仅将模块公开给 Get-ModuleImport-Module

可以替代此行为,使用 -SkipEditionCheck 开关参数显示所有模块。 我们还向表输出添加了 PSEdition 属性。

-lp 是所有 -LiteralPath 参数的别名

我们为具有 -LiteralPath 参数的所有内置 PowerShell cmdlet 创建了标准参数别名 -lp

如果 a*b 实际上不存在,则修复 Get-Item -LiteralPath a*b 以返回错误

以前,-LiteralPath 给定的通配符将将其视为与 -Path 相同,如果通配符未找到任何文件,它将以无提示方式退出。 正确的行为应该是,-LiteralPath 为文本,因此,如果文件不存在,则它应出错。 更改就是将与 -Literal 一起使用的通配符视作文本。

将工作目录设置为 Start-Job 中的当前目录

Start-Job cmdlet 现在使用当前目录作为新作业的工作目录。

*-Computer cmdlet 中删除 -Protocol

由于 CoreFX 中的 RPC 远程处理问题(尤其是在非 Windows 平台上)以及为了在 PowerShell 中保持一致的远程处理体验,已从 \*-Computer cmdlet 中移除了 -Protocol 参数。 远程处理功能不再支持 DCOM。 以下 cmdlet 仅支持 WSMAN 远程处理:

  • Rename-Computer
  • Restart-Computer
  • Stop-Computer

*-Service cmdlet 中删除 -ComputerName

为了鼓励一致使用 PSRP,-ComputerName 参数已从 *-Service cmdlet 中删除。

修复 Get-Content -Delimiter,使其在返回的行中不包含分隔符

以前,使用 Get-Content -Delimiter 时的输出不一致且不方便,因为它需要进一步处理数据以删除分隔符。 此更改将删除返回行中的分隔符。

Format-Hex 的更改

-Raw 参数现在是“no-op”(因为它不起作用)。 今后,所有输出都以包含其类型的所有字节的数字的真实表示形式显示。 这是此更改之前 -Raw 参数的作用。

Get-ComputerInfo 属性名称中的拼写错误修复

BiosSerialNumber 被错误地拼写为 BiosSeralNumber,现已更正为正确的拼写。

添加 Get-StringHashGet-FileHash cmdlet

此更改是 CoreFX 不支持某些哈希算法,因此它们不再可用:

  • MACTripleDES
  • RIPEMD160

Get-* cmdlet 上添加一个验证,以便在传递 $null 时返回所有对象,而不是产生错误。

$null 传递给以下任何项,现在会引发错误:

  • Get-Credential -UserName
  • Get-Event -SourceIdentifier
  • Get-EventSubscriber -SourceIdentifier
  • Get-Help -Name
  • Get-PSBreakpoint -Script
  • Get-PSProvider -PSProvider
  • Get-PSSessionConfiguration -Name
  • Get-Runspace -Name
  • Get-RunspaceDebug -RunspaceName
  • Get-Service -Name
  • Get-TraceSource -Name
  • Get-Variable -Name

Import-Csv 中添加对 W3C 扩展日志文件格式的支持

以前,Import-Csv cmdlet 不能用于直接导入 W3C 扩展日志格式的日志文件,还需要执行其他作。 通过此更改,支持 W3C 扩展日志格式。

当 CSV 文件中存在类型信息时,Import-Csv 在导入时应用 pstypenames

以前,使用 Export-Csv 导出的对象(带有使用 ConvertFrom-Csv 导入的 TypeInformation)已不保留类型信息。 如果 CSV 文件中有可用的类型信息,此更改会将其添加到 pstypenames 字段。

-NoTypeInformationExport-Csv 的默认值

以前,Export-Csv cmdlet 将输出注释作为包含对象类型名称的第一行。 默认情况下,更改会排除类型信息,因为大多数 CSV 工具无法理解该信息。 此更改旨在解决客户反馈问题。

使用 -IncludeTypeInformation 保留以前的行为。

允许为 Remove-Item 在注册表路径中使用 *

以前,-LiteralPath 给定的通配符将将其视为与 -Path 相同,如果通配符未找到任何文件,它将以无提示方式退出。 正确的行为应该是,-LiteralPath 为文本,因此,如果文件不存在,则它应出错。 更改就是将与 -Literal 一起使用的通配符视作文本。

Group-Object 现在对组进行排序

作为性能改进的一部分,Group-Object 现在返回组的排序列表。 虽然不应依赖于顺序,但如果想要第一组,则可能会被此更改所破坏。 我们决定,这种性能改进值得改变,因为依赖于以前的行为的影响很低。

Measure-Object 中的标准偏差

Measure-Object 中的输出现在包括 StandardDeviation 属性。

Get-Process | Measure-Object -Property CPU -AllStats
Count             : 308
Average           : 31.3720576298701
Sum               : 9662.59375
Maximum           : 4416.046875
Minimum           :
StandardDeviation : 264.389544720926
Property          : CPU

Get-PfxCertificate -Password

Get-PfxCertificate 现在具有 Password 参数,这个参数需要 SecureString。 这样就可以以非交互方式使用它:

$certFile = '\\server\share\pwd-protected.pfx'
$certPass = Read-Host -AsSecureString -Prompt 'Enter the password for certificate: '

$certThumbPrint = (Get-PfxCertificate -FilePath $certFile -Password $certPass ).ThumbPrint

删除 more 函数

过去,PowerShell 在 Windows 上发布了一个名为 more 的函数,该函数包装 more.com。 该函数现已删除。

此外,help 函数已更改为在 Windows 平台上使用 more.com,在非 Windows 平台上使用由 $Env:PAGER 指定的系统默认寻呼器。

cd DriveName: 现在将用户返回到该驱动器中的当前工作目录

以前,使用 Set-Locationcd 返回到 PSDrive,将用户发送到该驱动器的默认位置。 现在会将用户发送到该会话最后一个已知的当前工作目录。

cd - 返回到上一目录

C:\Windows\System32> cd C:\
C:\> cd -
C:\Windows\System32>

或在 Linux 上:

PS /etc> cd /usr/bin
PS /usr/bin> cd -
PS /etc>

此外,cdcd -- 更改为 $HOME

Update-Help 更改为非管理员命令

根据热门需求,Update-Help 不再需要以管理员身份运行。 Update-Help 现在默认将帮助文件保存到用户特定的文件夹中。

Where-Object -Not

-Not 参数添加到 Where-Object后,可以在管道中过滤掉不存在属性或具有空/无效属性值的对象。

例如,此命令返回未定义任何依赖服务的所有服务:

Get-Service | Where-Object -Not DependentServices

对 Web Cmdlet 的更改

Web Cmdlet 的基础 .NET API 已更改为 System.Net.Http.HttpClient。 此更改提供了许多好处。 但是,此更改以及缺乏与 Internet Explorer 的互操作性,导致 Invoke-WebRequestInvoke-RestMethod中的多个重大变更。

  • Invoke-WebRequest 现在仅支持基本 HTML 分析。 Invoke-WebRequest 始终返回 BasicHtmlWebResponseObject 对象。 已删除 ParsedHtmlForms 属性。
  • BasicHtmlWebResponseObject.Headers 值现在是 String[],而不是 String
  • BasicHtmlWebResponseObject.BaseResponse 现在是 System.Net.Http.HttpResponseMessage 对象。
  • Web Cmdlet 异常上的 Response 属性现在是 System.Net.Http.HttpResponseMessage 对象。
  • -Headers-UserAgent 参数现在默认使用严格的 RFC 标头分析。 这可以使用 -SkipHeaderValidation 绕过。
  • 不再支持 file://ftp:// URI 方案。
  • 不再采用 System.Net.ServicePointManager 设置。
  • macOS 目前没有可用的基于证书的身份验证。
  • 使用 -Credential 而不是 http:// URI 会导致错误。 使用 https:// URI 或提供 -AllowUnencryptedAuthentication 参数来抑制错误。
  • -MaximumRedirection 现在在重定向尝试超过提供的限制时生成终止错误,而不是返回上次重定向的结果。
  • 在 PowerShell 6.2 中,对 JSON 响应的 UTF-8 编码进行了默认更改。 如果未为 JSON 响应提供字符集,则默认使用的编码应为符合 RFC 8259 的 UTF-8。
  • 对于 application-json 响应,默认编码设置为 UTF-8
  • 添加了 -SkipHeaderValidation 参数,以允许不符合标准的 Content-Type 标头
  • 添加了 -Form 参数以支持简化的 multipart/form-data 支持
  • 合规且不区分大小写的关系键处理
  • 为 Web cmdlet 添加了 -Resume 参数

Invoke-RestMethod 在未返回任何数据时返回有用信息

当 API 仅返回 null时,Invoke-RestMethod 将它序列化为字符串 "null" 而不是 $null。 此项更改修复了 Invoke-RestMethod 中的逻辑,以便将有效的单个值 JSON null 文本正确序列化为 $null

当通过未加密的连接发送 -Credential 时,Web Cmdlet 会发出警告

使用 HTTP 时,包含密码的内容以明文形式发送。 默认情况下,此更改不允许这样做,如果在不安全的情况下传递凭据,则返回错误。 用户可以使用 -AllowUnencryptedAuthentication 开关绕过此功能。

在 Web cmdlet 中使 -OutFile 参数像 -LiteralPath 一样工作

从 PowerShell 7.1 开始,web cmdlet 的 OutFile 参数的工作方式类似于 LiteralPath,并且不处理通配符。

API 更改

删除 AddTypeCommandBase

AddTypeCommandBase 类已从 Add-Type 中删除,以提高性能。 此类仅供 Add-Type cmdlet 使用,不应影响用户。

在 Add-Type 中删除了对 VisualBasic 这门语言的支持

过去,可以使用 Add-Type cmdlet 编译 Visual Basic 代码。 Visual Basic 很少与 Add-Type一起使用。 我们删除了此功能以减少 PowerShell 的大小。

已删除 RunspaceConfiguration 支持

以前,使用 API 以编程方式创建 PowerShell Runspace 时,可以使用旧版 RunspaceConfiguration 或较新的 InitialSessionState 类。 此更改删除了对 RunspaceConfiguration 的支持,仅支持 InitialSessionState

CommandInvocationIntrinsics.InvokeScript 将参数绑定到 $input 而不是 $args

形参的位置不正确会导致将实参作为输入而不是实参进行传递。

$PSVersionTable 中删除 ClrVersionBuildVersion 属性

$PSVersionTableClrVersion 属性对 CoreCLR 没有用。 最终用户不应使用该值来确定兼容性。

BuildVersion 属性与 Windows 版本相关联,该版本在非 Windows 平台上不可用。 使用 GitCommitId 属性检索 PowerShell 的确切生成版本。

实现 Unicode 转义分析

`u#### `u{####} 转换为相应的 Unicode 字符。 若要输出文本 `u,转义反引号: ``u

PS 函数中 ValueFromRemainingArguments 的参数绑定问题

ValueFromRemainingArguments 现在返回一些值作为数组,而不是本身是数组的单个值。

已清理 CommandTypes.WorkflowWorkflowInfoCleaned 的使用

清理与 System.Management.Automation中使用 CommandTypes.WorkflowWorkflowInfo 相关的代码。

这些次要的中断性变更主要影响帮助提供程序代码。

  • WorkflowInfo 的公共构造函数更改为内部构造函数。 我们不再支持工作流,因此不允许人们创建 Workflow 实例是有意义的。
  • 删除类型 System.Management.Automation.DebugSource,因为它仅用于工作流调试。
  • 从仅用于工作流调试的抽象类 调试器 中删除 SetParent 的重载。
  • 从派生类 RemotingJobDebugger 中删除 SetParent 的相同重载。

ScriptBlock 转换为委托时,不要将返回结果包装为 PSObject

ScriptBlock 转换为用于 C# 上下文的委托类型时,将结果包装在 PSObject 中会带来不必要的麻烦:

  • 当值转换为委托返回类型时,PSObject 实质上是已解包。 因此,PSObject 是不需要的。
  • 当委托返回类型 object时,它将包装在 PSObject 中,使其难以在 C# 代码中使用。

此更改后,返回的对象是基础对象。

远程通信支持

在 Unix 平台上使用 WinRM 的 PowerShell 远程处理(PSRP)需要通过 HTTPS 进行 NTLM/Negotiate 或基本身份验证。 macOS 上的 PSRP 仅支持通过 HTTPS 进行基本身份验证。 非 Windows 平台不支持基于 Kerberos 的身份验证。

PowerShell 还支持在所有平台上(Windows、macOS 和 Linux)上通过 SSH 进行 PowerShell 远程处理(PSRP)。 有关详细信息,请参阅 PowerShell 中的 SSH 远程处理

适用于容器的 PowerShell Direct 尝试先使用 pwsh

PowerShell Direct 是 PowerShell 的一项功能,Hyper-V 允许在没有网络连接或其他远程管理服务的情况下连接到 Hyper-V VM 或容器。

过去,PowerShell Direct 使用容器上的内置 Windows PowerShell 实例进行连接。 现在,PowerShell Direct 先尝试使用 PATH 环境变量上任何可用的 pwsh.exe 进行连接。 如果 pwsh.exe 不可用,PowerShell Direct 会退回使用 powershell.exe

Enable-PSRemoting 现在为预览版本创建单独的远程处理终结点

Enable-PSRemoting 现在创建两个远程会话配置:

  • 一个用于 PowerShell 的主要版本。 例如,PowerShell.6。 根据“系统范围”的 PowerShell 6 会话配置,次要版本更新可依赖于此终结点
  • 一个版本特定的会话配置,例如:PowerShell.6.1.0

如果想要在同一台计算机上安装和访问多个 PowerShell 6 版本,则此行为非常有用。

此外,运行 Enable-PSRemoting cmdlet 后,PowerShell 预览版现在可以获得自己的远程会话配置:

C:\WINDOWS\system32> Enable-PSRemoting

如果以前未设置 WinRM,则输出可能有所不同。

WinRM is already set up to receive requests on this computer.
WinRM is already set up for remote management on this computer.

然后,可以查看 PowerShell 6 预览版和稳定版本的单独 PowerShell 会话配置,以及每个特定版本。

Get-PSSessionConfiguration
Name          : PowerShell.6.2-preview.1
PSVersion     : 6.2
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : PowerShell.6-preview
PSVersion     : 6.2
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : powershell.6
PSVersion     : 6.1
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

Name          : powershell.6.1.0
PSVersion     : 6.1
StartupScript :
RunAsUser     :
Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed

SSH 支持的 user@host:port 语法

SSH 客户端通常支持采用 user@host:port格式的连接字符串。 添加 SSH 作为 PowerShell 远程处理协议后,我们添加了对此连接字符串格式的支持:

Enter-PSSession -HostName fooUser@ssh.contoso.com:2222

可以通过环境变量禁用遥测

PowerShell 在启动时将基本遥测数据发送到Microsoft。 数据包括 OS 名称、OS 版本和 PowerShell 版本。 通过此数据,我们可以更好地了解使用 PowerShell 的环境,并允许我们确定新功能和修补程序的优先级。

要选择退出此遥测,请将环境变量 POWERSHELL_TELEMETRY_OPTOUT 设置为 trueyes1。 我们不再支持删除文件 DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY 以禁用遥测。