about_PowerShell_Editions
Short description
Different editions of PowerShell run on different underlying runtimes.
Long description
From PowerShell 5.1, there are multiple editions of PowerShell that each run on a different .NET runtime. As of PowerShell 6.0 there are two editions of PowerShell:
- Desktop, which runs on .NET Framework. PowerShell 4 and below, as well as PowerShell 5.1 are available for full-featured Windows editions like Windows Desktop, Windows Server, Windows Server Core and most other Windows operating systems. This is the original PowerShell edition and is included in the default installation of the operating system.
- Core, which runs on .NET Core. PowerShell 6.0 and later is installed side-by-side with earlier PowerShell releases on full-featured Windows editions, some reduced-footprint Windows editions such as Windows Nano Server and Windows IoT, or on non-Windows platforms such as Linux and macOS.
Because the edition of PowerShell corresponds to its .NET runtime, it is the primary indicator of .NET API and PowerShell module compatibility; some .NET APIs, types or methods are not available in both .NET runtimes and this affects PowerShell scripts and modules that depend on them.
The $PSEdition
automatic variable
In PowerShell 5.1 and above, you can find out what edition you are running with
the $PSEdition
automatic variable:
$PSEdition
Core
In PowerShell 4 and below, this variable does not exist. $PSEdition
being
null should be treated as the same as having the value Desktop
.
Edition in $PSVersionTable
The $PSVersionTable
automatic variable also has PSEdition property in
PowerShell 5.1 and above:
$PSVersionTable
Name Value
---- -----
PSVersion 7.3.9
PSEdition Core
GitCommitId 7.3.9
OS Microsoft Windows 10.0.22621
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
The PSEdition field has the same value as the $PSEdition
automatic
variable.
The CompatiblePSEditions
module manifest field
PowerShell modules can declare what editions of PowerShell they are compatible
with using the CompatiblePSEditions
field of the module manifest.
For example, a module manifest declaring compatibility with both Desktop
and
Core
editions of PowerShell:
@{
ModuleVersion = '1.0'
FunctionsToExport = @('Test-MyModule')
CompatiblePSEditions = @('Desktop', 'Core')
}
An example of a module manifest with only Desktop
compatibility:
@{
ModuleVersion = '1.0'
FunctionsToExport = @('Test-MyModule')
CompatiblePSEditions = @('Desktop')
}
Omitting the CompatiblePSEditions
field from a module manifest will have the
same effect as setting it to Desktop
, since modules created before this field
was introduced were implicitly written for this edition.
For modules not shipped as part of Windows (i.e. modules you write or install
from the gallery), this field is informational only; PowerShell does not change
behavior based on the CompatiblePSEditions
field, but does expose it on the
PSModuleInfo
object (returned by Get-Module
) for your own logic:
New-ModuleManifest -Path .\TestModuleWithEdition.psd1 -CompatiblePSEditions Desktop,Core -PowerShellVersion '5.1'
$ModuleInfo = Test-ModuleManifest -Path .\TestModuleWithEdition.psd1
$ModuleInfo.CompatiblePSEditions
Desktop
Core
Note
The CompatiblePSEditions
module field is only compatible with PowerShell
5.1 and above. Including this field will cause a module to be incompatible
with PowerShell 4 and below. Since the field is purely informational, it can
be safely omitted in later PowerShell versions.
In PowerShell 6.1, Get-Module -ListAvailable
has had its formatter updated to
display the edition-compatibility of each module:
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...
Edition-compatibility for modules that ship as part of Windows
For modules that come as part of Windows (or are installed as part of a role or
feature), PowerShell 6.1 and above treat the CompatiblePSEditions
field
differently. Such modules are found in the Windows PowerShell system modules
directory (%windir%\System\WindowsPowerShell\v1.0\Modules
).
For modules loaded from or found in this directory, PowerShell 6.1 and above
uses the CompatiblePSEditions
field to determine whether the module will be
compatible with the current session and behaves accordingly.
When Import-Module
is used, a module without Core
in CompatiblePSEditions
will not be imported and an error will be displayed:
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
When Get-Module -ListAvailable
is used, modules without Core
in
CompatiblePSEditions
will not be displayed:
Get-Module -ListAvailable BitsTransfer
# No output
In both cases, the -SkipEditionCheck
switch parameter can be used to override
this behavior:
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,...
Warning
Import-Module -SkipEditionCheck
may appear to succeed for a module, but
using that module runs the risk of encountering an incompatibility later on;
while loading the module initially succeeds, a command may later call an
incompatible API and fail spontaneously.
Authoring PowerShell modules for edition cross-compatibility
When writing a PowerShell module to target both Desktop
and Core
editions
of PowerShell, there are things you can do to ensure cross-edition
compatibility.
The only true way to confirm and continually validate compatibility however is to write tests for your script or module and run them on all versions and editions of PowerShell you need compatibility with. A recommended testing framework for this is Pester.
PowerShell script
As a language, PowerShell works the same between editions; it is the cmdlets, modules and .NET APIs you use that are affected by edition compatibility.
Generally, scripts that work in PowerShell 6.1 and above will work with Windows PowerShell 5.1, but there are some exceptions.
PSScriptAnalyzer version 1.18+ has rules like PSUseCompatibleCommands and PSUseCompatibleTypes that are able to detect possibly incompatible usage of commands and .NET APIs in PowerShell scripts.
.NET assemblies
If you are writing a binary module or a module that incorporates .NET assemblies (DLLs) generated from source code, you should compile against .NET Standard and PowerShell Standard for compile-time compatibility validation of .NET and PowerShell API compatibility.
Although these libraries are able to check some compatibility at compile time, they won't be able to catch possible behavioral differences between editions. For this you must still write tests.