about_PowerShell_Editions

简短说明

不同版本的 PowerShell 在不同的基础运行时上运行。

长说明

从 PowerShell 5.1 起,PowerShell 有多个版本,每个版本都在不同的 .NET 运行时上运行。 从 PowerShell 6.0 起,PowerShell 有两个版本:

  • Desktop,在 .NET Framework 上运行。 PowerShell 4 及更低版本以及 PowerShell 5.1 可用于全功能 Windows 版本,例如 Windows Desktop、Windows Server、Windows Server Core 和大多数其他 Windows 操作系统。 这是原始 PowerShell 版本,包含在操作系统的默认安装中。
  • Core,在 .NET Core 上运行。 PowerShell 6.0 及更高版本与早期 PowerShell 版本并行安装在全功能 Windows 版本、一些占用空间较小的 Windows 版本(例如 Windows Nano Server 和 Windows IoT)或非 Windows 平台(例如 Linux 和 macOS)上。

由于 PowerShell 的版本与其 .NET 运行时相对应,因此它是 .NET API 和 PowerShell 模块兼容性的首要指标;某些 .NET API、类型或方法在两种 .NET 运行时中不可用,这会影响依赖于它们的 PowerShell 脚本和模块。

$PSEdition 自动变量

在 PowerShell 5.1 及更高版本中,可以使用 $PSEdition 自动变量查出正在运行的是哪个版本:

$PSEdition
Core

在 PowerShell 4 及更低版本中,此变量不存在。 $PSEdition 为 null 应被视为等同于具有值 Desktop

$PSVersionTable 中的版本

$PSVersionTable 自动变量在 PowerShell 5.1 及更高版本中还有 PSEdition 属性:

$PSVersionTable
Name                           Value
----                           -----
PSVersion                      7.2.2
PSEdition                      Core
GitCommitId                    7.2.2
OS                             Microsoft Windows 10.0.22000
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

PSEdition 字段的值与 $PSEdition 自动变量的值相同。

CompatiblePSEditions 模块清单字段

PowerShell 模块可以使用模块清单的 CompatiblePSEditions 字段声明与哪些版本的 PowerShell 兼容。

例如,声明与 PowerShell 的 DesktopCore 版本兼容的模块清单:

@{
    ModuleVersion = '1.0'
    FunctionsToExport = @('Test-MyModule')
    CompatiblePSEditions = @('Desktop', 'Core')
}

只有 Desktop 兼容性的模块清单示例:

@{
    ModuleVersion = '1.0'
    FunctionsToExport = @('Test-MyModule')
    CompatiblePSEditions = @('Desktop')
}

在模块清单中省略 CompatiblePSEditions 字段与将其设置为 Desktop 具有相同效果,因为在引入此字段之前创建的模块是针对此版本隐式编写的。

对于未作为 Windows 的一部分提供的模块(即你编写的或从库中安装的模块),此字段只是为了提供信息;PowerShell 不会根据 CompatiblePSEditions 字段更改行为,但是会按照你的逻辑在 PSModuleInfo 对象(由 Get-Module 返回)上公开它:

New-ModuleManifest -Path .\TestModuleWithEdition.psd1 -CompatiblePSEditions Desktop,Core -PowerShellVersion '5.1'
$ModuleInfo = Test-ModuleManifest -Path .\TestModuleWithEdition.psd1
$ModuleInfo.CompatiblePSEditions
Desktop
Core

注意

CompatiblePSEditions 模块字段仅与 PowerShell 5.1 及更高版本兼容。 包括此字段会导致模块与 PowerShell 4 及更低版本不兼容。 由于该字段纯粹是为了提供信息,因此可以在更高的 PowerShell 版本中放心地省略该字段。

在 PowerShell 6.1 中,Get-Module -ListAvailable 更新了其格式化程序以显示每个模块的版本兼容性:

Get-Module -ListAvailable

    Directory: C:\Users\me\Documents\PowerShell\Modules

ModuleType Version    Name                   PSEdition ExportedCommands
---------- -------    ----                   --------- ----------------
Script     1.4.0      Az                     Core,Desk
Script     1.3.1      Az.Accounts            Core,Desk {Disable-AzDataCollection, Disable-AzContextAutosave, E...
Script     1.0.1      Az.Aks                 Core,Desk {Get-AzAks, New-AzAks, Remove-AzAks, Import-AzAksCreden...

...

Script     4.4.0      Pester                 Desk      {Describe, Context, It, Should...}
Script     1.18.0     PSScriptAnalyzer       Desk      {Get-ScriptAnalyzerRule, Invoke-ScriptAnalyzer, Invoke-...
Script     1.0.0      WindowsCompatibility   Core      {Initialize-WinSession, Add-WinFunction, Invoke-WinComm...

作为 Windows 的一部分提供的模块的版本兼容性

对于作为 Windows 的一部分提供(或作为角色或功能的一部分安装)的模块,PowerShell 6.1 及更高版本以不同的方式对待 CompatiblePSEditions 字段。 此类模块位于 Windows PowerShell 系统模块目录 (%windir%\System\WindowsPowerShell\v1.0\Modules) 中。

对于从此目录加载的或在此目录中找到的模块,PowerShell 6.1 及更高版本使用 CompatiblePSEditions 字段来确定该模块是否会与当前会话兼容,并会表现出相应的功能。

使用 Import-Module 时,不会导入 CompatiblePSEditions 中没有 Core 的模块,会显示错误:

Import-Module BitsTransfer
Import-Module : Module 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.psd1'
 does not support current PowerShell edition 'Core'. Its supported editions are 'Desktop'. Use 'Import-Module
 -SkipEditionCheck' to ignore the compatibility of this module.
At line:1 char:1
+ Import-Module BitsTransfer
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ResourceUnavailable: (C:\WINDOWS\system32\u2026r\BitsTransfer.psd1:String)
 [Import-Module], InvalidOperationException
+ FullyQualifiedErrorId : Modules_PSEditionNotSupported,Microsoft.PowerShell.Commands.ImportModuleCommand

使用 Get-Module -ListAvailable 时,不会显示 CompatiblePSEditions 中没有 Core 的模块:

Get-Module -ListAvailable BitsTransfer
# No output

在这两种情况下,都可以使用 -SkipEditionCheck 开关参数替代此行为:

Get-Module -ListAvailable -SkipEditionCheck BitsTransfer

    Directory: C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules

ModuleType Version    Name           PSEdition ExportedCommands
---------- -------    ----           --------- ----------------
Manifest   2.0.0.0    BitsTransfer   Desk      {Add-BitsFile, Complete-BitsTransfer, Get-BitsTransfer,...

警告

Import-Module -SkipEditionCheck 对于某个模块来说可能看起来很成功,但使用该模块可能会遇到稍后出现不兼容情况的风险;虽然加载模块的操作最初会成功,但某个命令稍后可能会自发调用不兼容的 API 并失败。

编写 PowerShell 模块以实现跨版本兼容性

编写要面向 Desktop 版和 Core 版 PowerShell 的 PowerShell 模块时,可以采取一些措施来确保跨版本兼容性。

但是,确认并持续验证兼容性的唯一真正方法是为脚本或模块编写测试,并在你需要兼容的所有 PowerShell 版本上运行这些测试。 为此推荐的测试框架是 Pester

PowerShell 脚本

作为一种语言,PowerShell 在不同版本之间的工作方式相同;是你使用的 cmdlet、模块和 .NET API 会受到版本兼容性的影响。

通常,在 PowerShell 6.1 及更高版本中工作的脚本适用于 Windows PowerShell 5.1,但存在一些例外情况。

PSScriptAnalyzer 版本 1.18+ 具有 PSUseCompatibleCommandsPSUseCompatibleTypes 等规则,这些规则能够检测出 PowerShell 脚本中命令和 .NET API 的可能不兼容的用法。

.NET 程序集

如果要编写一个二进制模块或一个包含从源代码生成的 .NET 程序集 (DLL) 的模块,则应针对 .NET StandardPowerShell Standard 进行编译,以便对 .NET 和 PowerShell API 兼容性进行编译时兼容性验证。

尽管这些库能够在编译时检查某些兼容性,但它们无法捕获版本之间可能存在的行为差异。 因此,仍必须编写测试。

另请参阅