What's New in PowerShell Core 6.0
PowerShell Core 6.0 is a new edition of PowerShell that is cross-platform (Windows, macOS, and Linux), open-source, and built for heterogeneous environments and the hybrid cloud.
Moved from .NET Framework to .NET Core
PowerShell Core uses .NET Core 2.0 as its runtime. .NET Core 2.0 enables PowerShell Core to work on multiple platforms (Windows, macOS, and Linux). PowerShell Core also exposes the API set offered by .NET Core 2.0 to be used in PowerShell cmdlets and scripts.
Windows PowerShell used the .NET Framework runtime to host the PowerShell engine. This means that Windows PowerShell exposes the API set offered by .NET Framework.
The APIs shared between .NET Core and .NET Framework are defined as part of .NET Standard.
For more information on how this affects module/script compatibility between PowerShell Core and Windows PowerShell, see Backwards compatibility with Windows PowerShell.
Support for macOS and Linux
PowerShell now officially supports macOS and Linux, including:
- Windows 7, 8.1, and 10
- Windows Server 2008 R2, 2012 R2, 2016
- Windows Server Semi-Annual Channel
- Ubuntu 14.04, 16.04, and 17.04
- Debian 8.7+, and 9
- CentOS 7
- Red Hat Enterprise Linux 7
- OpenSUSE 42.2
- Fedora 25, 26
- macOS 10.12+
Our community has also contributed packages for the following platforms, but they are not officially supported:
- Arch Linux
- Kali Linux
- AppImage (works on multiple Linux platforms)
We also have experimental (unsupported) releases for the following platforms:
- Windows on ARM32/ARM64
- Raspbian (Stretch)
A number of changes were made to in PowerShell Core 6.0 to make it work better on non-Windows systems. Some of these are breaking changes, which also affect Windows. Others are only present or applicable in non-Windows installations of PowerShell Core.
- Added support for native command globbing on Unix platforms.
morefunctionality respects the Linux
$PAGERand defaults to
less. This means you can now use wildcards with native binaries/commands (for example,
ls *.txt). (#3463)
- Trailing backslash is automatically escaped when dealing with native command arguments. (#4965)
- Ignore the
-ExecutionPolicyswitch when running PowerShell on non-Windows platforms because script signing is not currently supported. (#3481)
- Fixed ConsoleHost to honor
NoEchoon Unix platforms. (#3801)
Get-Helpto support case insensitive pattern matching on Unix platforms. (#3852)
powershellman-page added to package
A number of changes have been made on macOS and Linux to support filename characters not traditionally supported on Windows:
- Paths given to cmdlets are now slash-agnostic (both / and \ work as directory separator)
- XDG Base Directory Specification is now respected and used by default:
- The Linux/macOS profile path is located at
- The history save path is located at
- The user module path is located at
- The Linux/macOS profile path is located at
- Support for file and folder names containing the colon character on Unix. (#4959)
- Support for script names or full paths that have commas. (#4136) (Thanks to @TimCurwick!)
- Detect when
-LiteralPathis used to suppress wildcard expansion for navigation cmdlets. (#5038)
Get-ChildItemto work more like the *nix
ls -Rand the Windows
DIR /Snative commands.
Get-ChildItemnow returns the symbolic links encountered during a recursive search and does not search the directories that those links target. (#3780)
Linux and macOS tend to be case-sensitive while Windows is case-insensitive while preserving case. In general, PowerShell is case insensitive.
For example, environment variables are case-sensitive on macOS and Linux,
so the casing of the
PSModulePath environment variable has been standardized. (#3255)
Import-Module is case insensitive when it's using a file path to determine the module's name. (#5097)
Support for side-by-side installations
PowerShell Core is installed, configured, and executed separately from Windows PowerShell. PowerShell Core has a "portable" ZIP package. Using the ZIP package, you can install any number of versions anywhere on disk, including local to an application that takes PowerShell as a dependency. Side-by-side installation makes it easier to test new versions of PowerShell and migrating existing scripts over time. Side-by-side also enables backwards compatibility as scripts can be pinned to specific versions that they require.
By default, the MSI-based installer on Windows does an in-place update install.
The binary name for PowerShell Core has been changed from
This change provides a deterministic way for users to run PowerShell Core on machines to support side-by-side Windows PowerShell and PowerShell Core installations.
pwsh is also much shorter and easier to type.
Additional changes to
- Changed the first positional parameter from
-File. This change fixes the usage of
#!(aka as a shebang) in PowerShell scripts that are being executed from non-PowerShell shells on non-Windows platforms. It also means that you can run commands like
pwsh fooScriptwithout specifying
-File. However, this change requires that you explicitly specify
-Commandwhen trying to run commands like
pwsh.exe -Command Get-Command. (#4019)
- PowerShell Core accepts the
-Interactive) switch to indicate an interactive shell. (#3558) This allows PowerShell to be used as a default shell on Unix platforms.
- Removed parameters
pwsh -versionand built-in help for
pwsh.exeto align with other native tools. (#4958 & #4931) (Thanks @iSazonov)
- Invalid argument error messages for
-Commandand exit codes consistent with Unix standards (#4573)
-WindowStyleparameter on Windows. (#4573) Similarly, package-based installations updates on non-Windows platforms are in-place updates.
Backwards compatibility with Windows PowerShell
The goal of PowerShell Core is to remain as compatible as possible with Windows PowerShell. PowerShell Core uses .NET Standard 2.0 to provide binary compatibility with existing .NET assemblies. Many PowerShell modules depend on these assemblies (often times DLLs), so .NET Standard allows them to continue working with .NET Core. PowerShell Core also includes a heuristic to look in well-known folders--like where the Global Assembly Cache typically resides on disk--to find .NET Framework DLL dependencies.
Best efforts have been made to ensure that the PowerShell language and "built-in" modules (like
Microsoft.PowerShell.Utility, etc.) work the same as they do in Windows PowerShell.
In many cases, with the help of the community, we've added new capabilities and bug fixes to those cmdlets.
In some cases, due to a missing dependency in underlying .NET layers, functionality was removed or is unavailable.
Most of the modules that ship as part of Windows (for example,
Storage, etc.) and other Microsoft products including Azure and Office have not been explicitly ported to .NET Core yet.
The PowerShell team is working with these product groups and teams to validate and port their existing modules to PowerShell Core.
With .NET Standard and CDXML, many of these traditional Windows PowerShell modules do seem to work in PowerShell Core,
but they have not been formally validated, and they are not formally supported.
By installing the
you can use Windows PowerShell modules by appending the Windows PowerShell
PSModulePath to your PowerShell Core
First, install the
WindowsPSModulePath module from the PowerShell Gallery:
# Add `-Scope CurrentUser` if you're installing as non-admin Install-Module WindowsPSModulePath -Force
After installing this module,
Add-WindowsPSModulePath cmdlet to add the Windows PowerShell
PSModulePath to PowerShell Core:
# Add this line to your profile if you always want Windows PowerShell PSModulePath Add-WindowsPSModulePath
PowerShell Core adds support for Docker containers for all the major platforms we support (including multiple Linux distros, Windows Server Core, and Nano Server).
SSH-based PowerShell Remoting
The PowerShell Remoting Protocol (PSRP) now works with the Secure Shell (SSH) protocol in addition to the traditional WinRM-based PSRP.
This means that you can use cmdlets like
New-PSSession and authenticate using SSH.
All you have to do is register PowerShell as a subsystem with an OpenSSH-based SSH server,
and you can use your existing SSH-based authenticate mechanisms (like passwords or private keys) with the traditional
For more information on configuring and using SSH-based remoting, see PowerShell Remoting over SSH.
Default encoding is UTF-8 without a BOM
In the past, Windows PowerShell cmdlets like
Set-Content used different encodings, such as ASCII and UTF-16.
The variance in encoding defaults created problems when mixing cmdlets without specifying an encoding.
Non-Windows platforms traditionally use UTF-8 without a Byte Order Mark (BOM) as the default encoding for text files. More Windows applications and tools are moving away from UTF-16 and towards BOM-less UTF-8 encoding. PowerShell Core changes the default encoding to conform with the broader ecosystems.
This means that all built-in cmdlets that use the
-Encoding parameter use the
UTF8NoBOM value by default.
The following cmdlets are affected by this change:
These cmdlets have also been updated so that the
-Encoding parameter universally accepts
The default value of
$OutputEncoding has also been changed to UTF-8.
As a best practice, you should explicitly set encodings in scripts using the
-Encoding parameter to produce deterministic behavior across platforms.
Support backgrounding of pipelines with ampersand (
& at the end of a pipeline causes the pipeline to be run as a PowerShell job.
When a pipeline is backgrounded, a job object is returned.
Once the pipeline is running as a job, all of the standard
*-Job cmdlets can be used to manage the job.
Variables (ignoring process-specific variables) used in the pipeline are automatically copied to the job so
Copy-Item $foo $bar & just works.
The job is also run in the current directory instead of the user's home directory.
For more information about PowerShell jobs, see about_Jobs.
SemVer 2.0. (#5037) (Thanks @iSazonov!)
- Changed default
0.0.1to align with SemVer. (#4842) (Thanks @LDSpits)
semveras a type accelerator for
System.Management.Automation.SemanticVersion. (#4142) (Thanks to @oising!)
- Enabled comparison between a
SemanticVersioninstance and a
Versioninstance that is constructed only with
- Implement Unicode escape parsing so that users can use Unicode characters as arguments, strings, or variable names. (#3958) (Thanks to @rkeithhill!)
- Added new escape character for ESC:
- Added support for converting enums to string (#4318) (Thanks @KirkMunro)
- Fixed casting single element array to a generic collection. (#3170)
- Added character range overload to the
'a'..'z'returns characters from 'a' to 'z'. (#5026) (Thanks @IISResetMe!)
- Fixed variable assignment to not overwrite read-only variables
- Push locals of automatic variables to 'DottedScopes' when dotting script cmdlets (#4709)
- Enable use of 'Singleline, Multiline' option in split operator (#4721) (Thanks @iSazonov)
$PSVersionTablehas four new properties:
PSEdition: This is set to
Coreon PowerShell Core and
Desktopon Windows PowerShell
GitCommitId: This is the Git commit ID of the Git branch or tag where PowerShell was built. On released builds, it will likely be the same as
OS: This is an OS version string returned by
Platform: This is returned by
[System.Environment]::OSVersion.PlatformIt is set to
MacOSXon macOS, and
- Removed the
$PSVersionTable. This property was strongly tied to the Windows build version. Instead, we recommend that you use
GitCommitIdto retrieve the exact build version of PowerShell Core. (#3877) (Thanks to @iSazonov!)
$PSVersionTable. This property is irrelevant for .NET Core, and was only preserved in .NET Core for specific legacy purposes that are inapplicable to PowerShell.
- Added three new automatic variables to determine whether PowerShell is running in a given OS:
GitCommitIdto PowerShell Core banner. Now you don't have to run
$PSVersionTableas soon as you start PowerShell to get the version! (#3916) (Thanks to @iSazonov!)
- Add a JSON config file called
$PSHometo store some settings required before startup time (e.g.
- Don't block pipeline when running Windows EXE's
- Enabled enumeration of COM collections. (#4553)
Remove-AliasCommand. (#5143) (Thanks @PowershellNinja!)
Remove-Serviceto Management module. (#4858) (Thanks @joandrsn!)
- Add certificate authentication support for web cmdlets. (#4646) (Thanks @markekraus)
- Add support for content headers to web cmdlets. (#4494 & #4640) (Thanks @markekraus)
- Add multiple link header support to Web Cmdlets. (#5265) (Thanks @markekraus!)
- Support Link header pagination in web cmdlets (#3828)
Invoke-WebRequest, when the response includes a Link header we create a RelationLink property as a Dictionary representing the URLs and
relattributes and ensure the URLs are absolute to make it easier for the developer to use.
Invoke-RestMethod, when the response includes a Link header we expose a
-FollowRelLinkswitch to automatically follow
rellinks until they no longer exist or once we hit the optional
-CustomMethodparameter to web cmdlets to allow for non-standard method verbs. (#3142) (Thanks to @Lee303!)
SslProtocolsupport to Web Cmdlets. (#5329) (Thanks @markekraus!)
- Add Multipart support to web cmdlets. (#4782) (Thanks @markekraus)
-NoProxyto web cmdlets so that they ignore the system-wide proxy setting. (#3447) (Thanks to @TheFlyingCorpse!)
- User Agent of Web Cmdlets now reports the OS platform (#4937) (Thanks @LDSpits)
-SkipHeaderValidationswitch to web cmdlets to support adding headers without validating the header value. (#4085)
- Enable web cmdlets to not validate the HTTPS certificate of the server if required.
- Add authentication parameters to web cmdlets. (#5052) (Thanks @markekraus)
-Authenticationthat provides three options: Basic, OAuth, and Bearer.
-Tokento get the bearer token for OAuth and Bearer options.
-AllowUnencryptedAuthenticationto bypass authentication that is provided for any transport scheme other than HTTPS.
Invoke-RestMethodto enable the capture of response headers. (#4888) (Thanks @markekraus)
- Fix web cmdlets to include the HTTP response in the exception when the response status code is not success. (#3201)
- Change web cmdlets
PowerShell. (#4914) (Thanks @markekraus)
- Add explicit
- Fix web cmdlets
-SkipHeaderValidationto work with non-standard User-Agent headers. (#4479 & #4512) (Thanks @markekraus)
ConvertFrom-Jsonto return a
Hashtableinstead. (#5043) (Thanks @bergmeister!)
- Use prettier formatter with
ConvertTo-Jsonoutput. (#2787) (Thanks to @kittholland!)
Jobjectserialization support to
ConvertFrom-Jsonto deserialize an array of strings from the pipeline that together construct a complete JSON string. This fixes some cases where newlines would break JSON parsing. (#3823)
- Remove the
AliasProperty "Count"defined for
System.Array. This removes the extraneous
Countproperty on some
ConvertFrom-Jsonoutput. (#3231) (Thanks to @PetSerAl!)
ConvertFrom-Csv. (#5389) (Thanks @markekraus!)
CRLFas line delimiters. (#5363) (Thanks @iSazonov!)
-NoTypeInformationthe default on
ConvertTo-Csv. (#5164) (Thanks @markekraus)
- Add properties
ServiceControllerobjects returned by
Get-Service. (#4907) (Thanks @joandrsn)
- Add functionality to set credentials on
Set-Servicecommand. (#4844) (Thanks @joandrsn)
- Add a parameter to
-FollowSymlinkthat traverses symlinks on demand, with checks for link loops. (#4020)
CSharpVersion7. (#3933) (Thanks to @iSazonov)
- Remove the
Microsoft.PowerShell.LocalAccountsmodule due to the use of unsupported APIs until a better solution is found. (#4302)
- Remove the
Microsoft.PowerShell.Diagnosticsdue to the use of unsupported APIs until a better solution is found. (#4303)
- Add support for
Invoke-Item -Path <folder>. (#4262)
Split-Pathso that you can split paths between the filename extension and the rest of the filename. (#2721) (Thanks to @powercode!)
- Add parameters
Sort-Objectfor Top/Bottom N sort
- Expose a process' parent process by adding the
System.Diagnostics.Process. (#2850) (Thanks to @powercode!)
- Use MB instead of KB for memory columns of
Out-String. (#5056) (Thanks @raghav710)
*to be used in registry path for
Get-Credentialand unify the prompt experience across platforms.
- Add the
Get-AuthenticodeSignaturecmdlets can now get file signature timestamp. (#4061)
- Remove unsupported
Get-Content -Delimiterto not include the delimiter in the array elements returned (#3706) (Thanks @mklement0)
ConvertTo-HTML(#4184) (Thanks @ergo3114)
-Confirm). (#3074) (Thanks to @iSazonov!)
Start-Processcmdlet (#4735) (Thanks @sarithsutha)
ValidateNotNullOrEmptytoo many existing parameters.
Enhanced the type inference in tab completion based on runtime variable values. (#2744) (Thanks to @powercode!) This enables tab completion in situations like:
$p = Get-Process $p | Foreach-Object Prio<tab>
Add Hashtable tab completion for
Select-Object. (#3625) (Thanks to @powercode)
- Enable argument auto-completion for
Select-Object. (#3443) (Thanks to @iSazonov!)
- Fix a bug in tab completion to make
native.exe --<tab>call into native completer. (#3633) (Thanks to @powercode!)
We've introduced a number of breaking changes in PowerShell Core 6.0. To read more about them in detail, see Breaking Changes in PowerShell Core 6.0.
- Support for remote step-in debugging for
Invoke-Command -ComputerName. (#3015)
- Enable binder debug logging in PowerShell Core
- Enable usage of the Filesystem provider from a UNC path. ($4998)
Split-Pathnow works with UNC roots
cdwith no arguments now behaves as
- Fixed PowerShell Core to allow use of paths that are more than 260 characters long. (#3960)
Bug fixes and performance improvements
We've made many improvements to performance across PowerShell, including in startup time, various built-in cmdlets, and interaction with native binaries.
We've also fixed a number of bugs within PowerShell Core. For a complete list of fixes and changes, check out our changelog on GitHub.
- PowerShell Core 6.0 added telemetry to the console host to report two values (#3620):
- the OS platform (
- the exact version of PowerShell (
- the OS platform (
If you want to opt-out of this telemetry, simply delete
POWERSHELL_TELEMETRY_OPTOUT environment variable with one of the following values:
Deleting this file or creating the variable bypasses all telemetry even before the first run of PowerShell.
We also plan on exposing this telemetry data and the insights we glean from the telemetry in the community dashboard.
You can find out more about how we use this data in this blog post.