A look at the open source PowerShell v6

By Richard Siddaway, IT Consultant and Author.

Richard Siddaway has over 25 years of experience in IT, predominantly working with the Microsoft stack. Richard is a multi-year PowerShell MVP, author of a number of books on PowerShell, Active Directory and Windows administration and a regular speaker at the PowerShell Summit and user groups. He blogs regularly on PowerShell and related topics.  

Windows PowerShell was first released in November 2006. It was an optional install for Windows Server 2008 and available as a separate download for Windows Vista and earlier client and server versions. Each subsequent wave of Windows releases has been accompanied by a new version of Windows PowerShell. The latest version, v5.1, appeared with Windows Server 2016 and the Windows 10 Anniversary update. You can also download v5.1 for a number of older versions of Windows.

The PowerShell world changed dramatically in August 2016 when it was announced that PowerShell was now an open source project. In addition, the project would create versions to run on Windows (Windows 7 and later or Windows Server 2008 R2 and later), numerous Linux distributions and Mac!

After numerous alpha and beta releases, the first product from open source PowerShell was released to General Availability in January 2018 as PowerShell v6.0. It was released as v6.0.1 shortly afterwards to deal with versioning issues on Linux and to use .NET core v2.0.5. You can download PowerShell v6 from the releases page of the GitHub repository, where you’ll also find installation instructions.

I’ll be comparing, and contrasting, Windows PowerShell v5.1 to PowerShell v6 in this article. The comparison will apply to earlier versions of Windows PowerShell as well – just note that features such as classes were introduced in v5.

The first thing to note is that PowerShell v6 is NOT a replacement for Windows PowerShell v5.1; You can install PowerShell v6 side-by-side with Windows PowerShell v5.1. Please notice the subtle but important difference between the names. Windows PowerShell vX refers to the version of PowerShell that ships in the box with Windows. PowerShell vX refers to the version from the open source project. The two versions also have different icons:

Windows PowerShell v5.1 on the left and PowerShell v6 on the right.

The other important difference is the version of .NET underlying the two versions of PowerShell. Windows PowerShell v5.1 uses the full .NET CLR. PowerShell v6 uses .NET Core, which is a cross-platform implementation of .NET that has Windows-specific features, amongst others, removed.

One very important difference to note is that the Windows PowerShell executable is powerShell.exe but in PowerShell v6 its changed to pwsh.exe. This is designed to reduce confusion when running both versions simultaneously. PowerShell v6 installs into ‘C:\program Files’ rather than ‘C:\Windows\System32’. Both will be on your path:

 PS> $env:Path -split ';'
C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\System32\Wbem
C:\WINDOWS\System32\WindowsPowerShell\v1.0\
C:\Program Files\PowerShell\6.0.1\
C:\Program Files\Microsoft VS Code\bin

Different executable names are useful in this case! You can call PowerShell.exe from pwsh.exe and vice versa.

PowerShell v6 is designed as a cross-platform implementation. As such there are a limited number of modules available on Windows compared to Windows PowerShell v5.1. The following are delivered in the core PowerShell v6 package for Windows:

  • CimCmdlets
  • Microsoft.PowerShell.Archive
  • Microsoft.PowerShell.Diagnostics
  • Microsoft.PowerShell.Host
  • Microsoft.PowerShell.Management
  • Microsoft.PowerShell.Security
  • Microsoft.PowerShell.Utility
  • Microsoft.WSMan.Management

In addition, the following add-on modules are available:

  • PackageManagement
  • PowerShellGet
  • PSDesiredStateConfiguration
  • PSDiagnostics
  • PSReadLine

One obvious difference is that Pester – the module that enables you to test your code – isn’t present as it is with Windows PowerShell v5.1. The decision was made to remove Pester from the PowerShell v6 package as Pester is evolving quickly and it was thought to be better to allow you to download the latest versions from the PowerShell gallery.

On Linux a number of modules from the above lists aren’t installed:

  • CimCmdlets
  • Microsoft.PowerShell.Diagnostics
  • Microsoft.WSMan.Management
  • PSDiagnostics

Even when a module exists in both PowerShell v6 and Windows PowerShell v5.1, the contents of the module aren’t necessarily the same. For example, the module Microsoft.PowerShell.Diagnostics doesn’t have the performance counter cmdlets that are present in Windows PowerShell v5.1 as shown in the figure:

PowerShell workflows have been removed from PowerShell v6 (they will be replaced eventually by cmdlets providing easier access to PowerShell runspaces) as have the WMI, Eventlog and performance counter cmdlets. PowerShell v6 doesn’t include the PowerShell Integrated Scripting Environment (ISE), as Visual Studio Code is the recommended editor for PowerShell scripts going forward. It’s cross-platform, so it can be installed on Linux as well as Windows, it supports many languages beside PowerShell and, probably the most important, the Terminal pane can be switched between Windows PowerShell v5.1 and PowerShell v6 if you have both installed. This provides a good development and testing environment if you need to create code that’s version and platform independent.

At this stage you may be thinking that PowerShell v6 isn’t going to be of any use to you, but there a number of reasons why you should include it in your administrator’s toolset. Firstly, the release cadence for PowerShell v6+ is much faster than Windows PowerShell has ever been. A new version of Windows PowerShell has appeared with each new version of Windows. The open source nature of the PowerShell project means that releases are much faster – the current plan for releases to occur is approximately every six months.

PowerShell v6.1 is under development and slated for release in June/July 2018, and you can take a look at the roadmap. A Windows PowerShell Compatibility Pack will also be introduced that will bring back the WMI, Eventlog and performance counter cmdlets, as well as some APIs that will enable some of the existing Windows PowerShell modules to work in PowerShell v6+.

Secondly, all future development of PowerShell will be through the open source project. If there is another version of Windows PowerShell, it will effectively be a cloned from the open source PowerShell project.

Thirdly, a lot of the current Windows PowerShell functionality will work with PowerShell v6. In addition to the PowerShell engine you’ll find a lot of modules – for instance the networking and storage modules – will work on systems running Windows 8 and later. These modules are provided by the appropriate Microsoft team rather than the PowerShell team. Many of these modules are CDXML modules – meaning they are based on a CIM class, with some clever XML and the cmdlets-over-objects technology turns them into PowerShell modules. You can recognise these modules by the .CDXML files they contain:

 PS> Get-ChildItem -Path C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ -Filter *.CDXML -Recurse | select DirectoryName -Unique

These modules should run in PowerShell v6, and script-based modules may run depending on what cmdlets and features they use. Binary modules are unlikely to be usable in PowerShell v6 as they are compiled against the full .NET CLR and may well use functionality not available in .NET Core.

You can append the Windows PowerShell v5.1 modules to your module path in PowerShell v6:

 $env:PSModulePath = $env:PSModulePath + ';C:\Windows\System32\WindowsPowerShell\v1.0\Modules\'

If you add that line to your PowerShell v6 profile you’ll be able to access these modules every time you start PowerShell v6. Speaking of profiles – the PowerShell v6 profiles are in:

 PS> $PROFILE
C:\Users\\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

As opposed to the PowerShell v5.1 profile in:

 PS> $PROFILE
C:\Users\\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

There are some modules that definitely won’t work under PowerShell v6. Many of the RSAT tools – such as Active Directory - are binary modules that won’t work in PowerShell v6. A few RSAT tools are CDXML based and should work, but the Exchange modules don’t work under PowerShell v6.

The relevant teams are being encouraged to make their modules work with PowerShell v6 as well as Windows PowerShell v5.1

The Windows Compatibility pack mentioned earlier will also load a number of .NET core classes you’ll be able to use in scripts. You can do this now using the PSCoreWindowsCompat module from the PowerShell gallery:

 PS> Find-Module PSCoreWindowsCompat | Format-List Version, Name, Description

Version : 0.1.0.4
Name : PSCoreWindowsCompat
Description : Provides the Microsoft.Windows.Compatibility Pack to PowerShell
Core on 64-bit Windows Only. This module is not supported on
non-Windows platforms nor on 32-bit Windows.

You can download and install the module using:

 PS> Install-Module PSCoreWindowsCompat -Force

Once you have the module installed you can use the additional .NET core namespaces. One of them is System.DirectoryServices which enables you to work with AD. You’ll have to script rather than using cmdlets (the AD cmdlets were first available in Windows Server 2008). If you were using PowerShell v1, or Windows Server 2003[R2] you might remember doing things like this:

 Import-Module -Name PSCoreWindowsCompat
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $dom.GetDirectoryEntry()

$search = [System.DirectoryServices.DirectorySearcher]$root
$search.Filter = "(&(objectclass=user)(objectcategory=user)(cn=*brown*))"
$results = $search.FindAll()

foreach ($result in $results){
$result.Properties |
Select-Object @{N="Name"; E={$_.name}}, @{N="SamAccountName"; E={$_.samaccountname}},
@{N="DistinguishedName"; E={$_.distinguishedname}}

}

You can use ISE to create the script and then run it in a PowerShell v6 console. Alternatively, you can create and run the code in Visual Studio Code:

VSCode has a similar view to ISE with the editing pane and output pane. You can also position the output pane to the right of the editor pane which is something I’d been asking for since ISE appeared in PowerShell v2! If you look closely at the bottom right of the figure you’ll see the PowerShell icon and 6.0 (session menu), indicating that we’re dealing with PowerShell v6. The default is for VSCode to work with Windows PowerShell but by clicking on the session menu you can select the version you’re working with.

Of course, it’s much easier when you can use the AD cmdlets:

 PS> Get-ADUser -Filter {Name -like "*Brown*"} |
select Name, SamAccountName, DistinguishedName

This example shows that you can overcome some of the current limitations of PowerShell v6 by reverting to an older style of working.

One of PowerShell’s big selling points is its ability to perform remote administration. You can create a PowerShell remoting session to a machine and either work interactively in the session or use Invoke-Command to send one or more commands to the remote machine. This all occurs over the industry standard WSMAN protocol. This works very well inside your domain but breaks down due to Kerberos issues when trying to access machines that are in a workgroup. In Windows PowerShell v5.1 you can only remote into Windows machines.

As an aside, a number of cmdlets in Windows PowerShell v5.1 have a -ComputerName parameter. This allows them to access remote machines, usually over RPC or DCOM calls. In PowerShell v6 the -ComputerName parameter is being, or has been, removed from these cmdlets. All remote access now goes through the remoting system which I take to include CIM sessions.

Windows PowerShell v5.1 on Hyper-V hosts running Windows 10 or Windows Server 2016 can use PowerShell Direct to create remoting sessions to virtual machines running Windows 10 or Windows Server 2016. These sessions run over the VM bus rather than using WSMAN. PowerShell v6 will work in a similar manner if you import the Hyper-V module as shown earlier. The Hyper-V module appears to work in PowerShell v6 but I’ve only done limited testing.

Creating a session to a VM requires a credential:

 PS> $credd = Get-Credential manticore\richard

And then you create the session:

 $s = New-PSSession -VMName W10PRV01 -Credential $credd

If you enter the session and retrieve the contents on $PSversionTable you’ll find you’re connected to a PowerShell v5.1 session:

PowerShell v6 supports traditional remoting over WSMAN between Windows systems. WSMAN-based remoting is being made available for Linux systems, but it’s not complete as of this release. PowerShell v6 also supports remoting over SSH, the de facto remote administration protocol in the Linux world. SSH support isn’t built in to PowerShell v6 so you need to install OpenSSH, another open source project. The OpenSSH deliverable is still flagged as being a beta release so there is the potential for changes before a production ready release is available.

You can view the OpenSSH installation instructions on GitHub. The good news is that the installation is easier than in the earlier versions but it still requires a number of manual steps. One of the items on the PowerShell v6 roadmap is simplifying the installation of OpenSSH.

The installation of OpenSSH and PowerShell v6 brings a couple of advantages. You can now perform PowerShell remoting to and from Linux systems and you have a potentially easier option for remoting to non-domain Windows machines.

Establishing a WSMAN remoting session to a Windows system is exactly the same as in earlier versions of PowerShell:

 PS> $sw = New-PSSession -ComputerName W16AS01

If you want to create a SSH-based session you use the -HostName and -UserName parameters:

 PS> $ss = New-PSSession -HostName W16AS01 -UserName 'manticore\richard'
The authenticity of host 'w16as01 (10.10.54.20)' can't be established.
ECDSA key fingerprint is SHA256:pC8WqT3dLIo1IMltN5qmn8jvKbMb0JAWt0pDLH31ld4.
Are you sure you want to continue connecting (yes/no)?
Please type 'yes' or 'no':
Warning: Permanently added 'w16as01,10.10.54.20' (ECDSA) to the list of known hosts.
richard@manticore@w16as01's password:

If you’ve not connected to the remote machine previously you’ll be asked if you want to continue, as the host is unknown. Once you’ve agreed, the host will be added to the known hosts list and you won’t be prompted again. You’ll then be prompted for the password; Note that you won’t get any visual feedback on Windows systems as you type your responses to this dialog, which can be disconcerting.

Once you have the sessions established you can access then using Invoke-Command:

 PS> Invoke-Command -Session $sw, $ss -ScriptBlock {$PSVersionTable.PSVersion}

Creating a remote session to a Linux system is similar:

Notice the information returned by $PSVersionTable on a Linux system and compare that with what’s returned by a Windows system:

 PS> $PSVersionTable

Name                          Value
----                          -----
PSVersion                     6.0.1
PSEdition                     Core
GitCommitId                   v6.0.1
OS Microsoft Windows          10.0.16299
Platform                      Win32NT
PSCompatibleVersions          {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion     2.3
SerializationVersion          1.1.0.1
WSManStackVersion             3.0

Remoting from a Linux system to a Windows system is just as straightforward:

Remoting over SSH also works to a Windows non-domain system without using the trusted hosts list or certificates.

You can avoid the need to manually enter the password when you create a SSH-based remoting session by using key-based authentication. Create public/private keys as described in this PowerShell team blog post, and distribute the keys to the relevant machines.

CIM sessions are created using WSMAN by default. You can revert to DCOM if required. You can’t create a CIM session over SSH.

PowerShell v6 is currently an interesting mix of new, old and missing functionality. The big question is should you be using it?

If you have a purely Windows environment with no, or very few non-domain joined systems, PowerShell v6 doesn’t have much to offer you. You’ll get your work done in Windows PowerShell v5.1. That doesn’t mean you should ignore v6 because that’s where the innovation is happening and future releases will close, and eventually eliminate, the feature gaps. At some stage you may end up with a more heterogeneous environment for which PowerShell v6 would be ideal management tool.

If you have a significant number of Windows non-domain joined systems and/or a significant number of Linux systems in your environment, then you should be investigating PowerShell v6 if you haven’t already started using it.

At the very least you should monitor what the open source PowerShell project is doing as it will help you keep up to date in a quickly changing world. I suspect many people will end up using Windows PowerShell v5.1 and PowerShell v6 side-by-side for the foreseeable future.