Monthly Archive


PowerShell v6

PowerShell v6: #7 Module paths

There is a very significant gap between the functionality available in PowerShell v6 as opposed to PowerShell v5.1. In part this is due to the underlying version of .NET but mainly to the defined module paths in the two versions.

In PowerShell v5.1 I have:

PS>  $env:PSModulePath -split ';'
C:\Program Files\WindowsPowerShell\Modules


In PowerShell v6 I have

PS C:\scripts> $env:PSModulePath -split ';'
C:\Program Files\PowerShell\Modules
c:\program files\powershell\6.0.0-rc\Modules


The vast majority of the module supplied with PowerShell v5.1 reside in C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules which PowerShell v6 can’t see.


Unless you add it in yourself

$env:PSModulePath = $env:PSModulePath + ';C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules'


I’ve appended the PowerShell v5.1 modules to the PowerShell v6 module path.


There’s still no guarantee that the modules will work – it depends on the module code and if it accesses .NET classes that aren’t available in .NET core.


You’ll have to use trial and error to determine what works. For instance:


all work. BUT they’re from CDXML modules based on CIM classes not binary modules. As a rule thumb I’d expect the CIM based modules to just work. Binary module will definitely be trial and error.

PowerShell v6: #6 Windows compatibility

PowerShell v1 through v5.1 have been based on the full .NET framework. PowerShell v6 is based on .NET core which is a cross platform subset of .NET that’s available for Windows, Linux and mac. This has meant that Powershell v6 on Windows is a poor relation of PowerShell v5.1 in terms of the functionality available – for instance the Active Directory module won’t run on PowerShell v6. This makes v6 a backward step for administering Windows. Steps are being taken that will improve Windows compatibility of PowerShell v6.


The .NET core team are releasing a Windows compatibility pack – see for what’s likely to be in it.

A number of cmdlets including:

WMI cmdlets

Eventlog cmdlets

PerCounter cmdlets


are ear marked for being ported to PowerShell v6 using the compatibility pack. When this happens and what else is will be included is unsure. You can follow the issue at

PowerShell v6: #5 Get-Uptime

One new feature of PowerShell v6 (its actually been available since alpha 13 but I’d missed it) is the Get-Uptime cmdlet


PS C:\scripts> Get-Uptime

Days              : 0 
Hours             : 2 
Minutes           : 57 
Seconds           : 6 
Milliseconds      : 0 
Ticks             : 106260000000 
TotalDays         : 0.122986111111111 
TotalHours        : 2.95166666666667 
TotalMinutes      : 177.1 
TotalSeconds      : 10626 
TotalMilliseconds : 10626000


You get a timespan object returned for the uptime.


If you want to get something similar in Windows PowerShell you need to access the Win32_OperatingSystem CIM class

PS>  (Get-Date) - (Get-CimInstance -ClassName Win32_OperatingSystem | select -ExpandProperty LastBootUpTime)

Days              : 0 
Hours             : 3 
Minutes           : 7 
Seconds           : 7 
Milliseconds      : 850 
Ticks             : 112278501750 
TotalDays         : 0.129951969618056 
TotalHours        : 3.11884727083333 
TotalMinutes      : 187.13083625 
TotalSeconds      : 11227.850175 
TotalMilliseconds : 11227850.175


Ah! We’re back to the days of the PowerShell one liner – though to be accurate it should one pipeliner.


Remember that Windows 8, 8.1 and 10 will only reset LastBootUpTime on a restart. If you  use Shutdown on the Start menu its effectively hibernating which explains why these versions of windows boot up so quickly.

PowerShell v6: #4 profiles

Windows PowerShell (v1-v5.1) has always used profiles to configure your PowerShell session.  You need execution policy set to something other than restricted so that the profile script can run.


You can have up to 4 profiles:

Description                Path 
-----------                ---- 
Current User, Current Host $Home\[My ]Documents\WindowsPowerShell\Profile.ps1 
Current User, All Hosts    $Home\[My ]Documents\Profile.ps1 
All Users, Current Host    $PsHome\Microsoft.PowerShell_profile.ps1 
All Users, All Hosts       $PsHome\Profile.ps1


Most people only use 1. I use $Home\[My ]Documents\Profile.ps1 as my profile as its easier to change then in $PShome.


In PowerShell v6 your profile options are

Description                Path 
-----------                ---- 
Current User, Current Host $Home\Documents\PowerShell\Profile.ps1 
Current User, All Hosts    $Home\Documents\Profile.ps1 
All Users, Current Host    $PsHome\Microsoft.PowerShell_profile.ps1 
All Users, All Hosts       $PsHome\Profile.ps1


The location of $PShome changes in PowerShell v6.  In Windows PowerShell v1 through v5.1  its:

PS>  $pshome

In PowerShell v6 its:

PS C:\scripts> $pshome
C:\Program Files\PowerShell\6.0.0-beta.9


Be careful of using $Home\Documents\Profile.ps1 as it will also be applied to Windows PowerShell. The safest place to put your PowerShell v6 profile is $Home\Documents\PowerShell\Profile.ps1 as it will still apply when you upgrade to the next version e.g. from a beta version to release candidate or full release.

PowerShell v6: #3 Release Candidate

The PowerShell team have announced the availability of the PowerShell v6 release candidate.


A release candidate is just about done with only bugs to resolve – in other words about what you can expect in the final delivery.


Some work is still required -


The full release of PowerShell 6.0 is expected to occur on 10 January 2018 according to the blog post. Work then commences on PowerShell 6.1 with beta releases every 3 weeks or so.

When is PowerShell not PowerShell?

When is PowerShell not PowerShell? When its PowerShell v6.


This applies to beta 9 and later


Check a v6 instance

PS C:\Program Files\PowerShell\6.0.0-beta.9> $PSVersionTable

Name                           Value 
 ----                           ----- 
PSVersion                      6.0.0-beta.9 
PSEdition                      Core 
GitCommitId                    v6.0.0-beta.9 
 OS                             Microsoft Windows 10.0.17035 
 Platform                       Win32NT 
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...} 
PSRemotingProtocolVersion      2.3 
WSManStackVersion              3.0

Now try and run PowerShell

 PS C:\Program Files\PowerShell\6.0.0-beta.9> powershell 
 Windows PowerShell 
 Copyright (C) Microsoft Corporation. All rights reserved.

PS>  $PSVersionTable

Name                           Value 
 ----                           ----- 
PSVersion                      5.1.17035.1000 
PSEdition                      Desktop 
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...} 
BuildVersion                   10.0.17035.1000 
CLRVersion                     4.0.30319.42000 
WSManStackVersion              3.0 
PSRemotingProtocolVersion      2.3 

You get your v5.1 instance! You HAVE to use pwsh

PS>  exit 
 PS C:\Program Files\PowerShell\6.0.0-beta.9> pwsh 
 PowerShell v6.0.0-beta.9 
 Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\Program Files\PowerShell\6.0.0-beta.9> $PSVersionTable

Name                           Value 
 ----                           ----- 
PSVersion                      6.0.0-beta.9 
PSEdition                      Core 
GitCommitId                    v6.0.0-beta.9 
 OS                             Microsoft Windows 10.0.17035 
 Platform                       Win32NT 
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...} 
PSRemotingProtocolVersion      2.3 
WSManStackVersion              3.0

The command to start PowerShell v6 on Linux is also pwsh.

This is wrong on so many levels that its difficult to explain. I know its supposed to enable the separation on v6 and any older versions in a side by side install but having to remember this adds another level of unnecessary thought to using PowerShell. I’ve been a big fan of PowerShell for over 12 years but v6 and the changes that are being made are in many instances a step backwards for an illusionary gain.

PowerShell v6: #2 Remoting

Ask any number of users and you’ll get at least that many different answers but at its core PowerShell is an administration tool. To be effective your administration tools have to be able to access remote machines. RDP is the traditional way to do this for GUI bound admins – should that be the coding challenged? PowerShell remoting is the answer scripting and automation.


In PowerShell v5.1 you have a number of remoting options.


The simplest uses DCOM/RPC at the individual cmdlet level e.g. the *-process; *-service; *-computer cmdlets. This gives you ease of use but depends on you being able to use DCOM remotely. DCOM is blocked by default by the Windows firewall and isn’t a network (router) friendly protocol. The advice is to use it where you can if you need to but you’re better off using PowerShell remoting.


PowerShell remoting, introduced in PowerShell uses WS-MAN for communication with the remote server. Your target needs remoting enabled and the WinRM service to be running. Remoting is enabled by default in Windows Server 2012 and later but has to be enabled in all client versions of Windows and Windows Server 2008 R2 and earlier.


Within a domain remoting is easy because Kerberos authentication is available dramatically reducing the need for credentials. There are a few issues though. Remoting out or or into the domain can be problematic because Kerberos doesn’t support that. You need to use the trusted hosts option (not recommended) or certificate based remoting (safer but harder to configure). There’s also the double hop issue to contend with where you can’t issue a command from computer A that runs on computer B and accesses computer C. You can overcome this using CredSSP or an AD based delegation option.



PowerShell v3 brought a further expansion in remoting option with the introduction of CIM Sessions. These provide remoting options over WS-MAN for the CIM cmdlets (the WMI cmdlets use DCOM) that are analogous to the PowerShell remoting options.


In PowerShell v6 the remoting options change.


The DCOM based remoting option for individual cmdlets has been or is in the process of being removed.


WS-MAN based PowerShell remoting is still available between Windows machines – v6 to v6 or v6 to earlier PowerShell version or earlier PowerShell version to v6. Between Windows machines WS-MAN based remoting works as you would expect with all of the same issues you’ve come know and love through PowerShell versions v2-v5.1.


You also get Linux to Windows remoting over WS-MAN (basic and NTLM based authentication only). You need to install the OMI provider - - and the PRSP package -


PowerShell v6 has switched to using SSH as the primary communication protocol for remoting. SSH (using the OpenSSH project which isn’t currently production ready )  will be the focus of future remoting development. SSH based remoting works for Linux <-> Linux, Linux <-> Windows, Windows <-> Linux, Windows <-> Windows but its PowerShell v6 only and won’t be back ported (current team statement) to earlier versions of PowerShell.


SSH based remoting works in the scenarios given above – see demos from PowerShell Summit 2017 – but has issues. Its a very painful process to install and enable OpenSSH on a Windows machine. Doing this across your environment would be a huge job. There is an install script (incomplete last time I looked) and a chocolately package if you use that package management option but its still no where as easy as enabling WS-MAN based remoting.


SSH based remoting supplies a great option for the remoting into and out a domain scenarios but the current reduction in functionality available through PowerShell v6 compared to v5.1 means that while you can create a remote session to the machine you may not be able to do what you need.


If you have OMI installed on your Linux box you can make CIM calls to that box and establish CIM sessions. You won’t get much back as there aren’t the equivalent CIM classes for Linux boxes that you’re used to on Windows. Installing OMI is a pre-requisite for DSC for Linux.


Remoting in PowerShell v6 is changing – some changes are beneficial and some will cause problems as they are very definitely breaking changes from earlier version of PowerShell. If you haven’t investigated PowerShell v6 you need to do so. You need to determine what remoting options you need in your environment and how PowerShell v6, v5,1 WS-MAN and SSH are going to coexist or what subset of those options you’ll use.

PowerShell v6: #1 major differences

In August 2016 PowerShell went open source. Since then we’ve seen 18 releases of alpha code and 8 beta release with another beta release imminent. This post - – from the PowerShell Team suggested a full release of PowerShell v6 before the end of 2017.


I’ve not written much about PowerShell v6 so far as its been rapidly changing but we’re beginning to see where PowerShell v6 is going. In this and a series of posts I’ll show you what’s different in PowerShell v6 – some good and some bad – what the important changes are and what impact that might have on your administration strategies.


The current version of Windows PowerShell – in Windows 10 and Server 2016 or WMF download is 5.1. As the above blog post states PowerShell 5.1 requires the FULL .NET Framework – currently 4.x – and will NOT receive major feature updates or low priority bug fixes (I read that as only security related bug fixes are likely).


PowerShell v6 is a fork of the v5.1 code but is based on .NET Core and will address bugs in the original 5.1 code, which won’t be ported back to PowerShell 5.1. PowerShell 6 uses .NET Standard 2.0 to provide binary compatibility with existing .NET assemblies which means that some but not all existing PowerShell modules will work under PowerShell v6.


PowerShell v6 isn’t an upgrade for PowerShell 5.1. It installs side-by-side meaning you can have multiple versions of PowerShell on the same machine.


Windows PowerShell (v1 – v5.1) is the Windows only version that shipped as part of the OS. PowerShell core (v6) is cross-platform with releases for Windows, Linux, macOS and docker -


The major differences between PowerShell v6 and the Windows PowerShell you’ve come to know and love are detailed on the v6 release notes -  In summary these include:

Allow * to be used in registry paths – breaking change
Remove -ShowWindow from Get-Help – breaking change
Fix incorrect position of a parameter which resulted in the args passed as input instead of as args for InvokeScript()  – breaking change
Enable transcription of native commands on non-Windows platforms
Add Remove-Service cmdlet
Added functionality to set credentials on Set-Service
Get-Date now supports more argument completion scenarios
Exclude -ComObject parameter of New-Object on unsupported (currently non-Windows)
Remove Workflows
Get-Content -Delimiter to not include the delimiter in the array elements returned
Add support for converting enums to string
Support SSH for remoting as well as WSMAN
Remove WMI cmdlets - CIM cmdlets are still available
Remove the *-Counter cmdlets
Move-Item cmdlet honors -Include, -Exclude, and -Filter parameters
Change positional parameter for powershell.exe from -Command to -File  – breaking change
Make change across PowerShell to support case sensitivity on *nix
Putting & at the end of a pipeline will cause the pipeline to be run as a PowerShell job.
Add -Extension and -LeafBase switches to Split-Path so that you can split paths between the filename extension and the rest of the filename
Fix Get-Help to not return multiple instances of the same help file


Plus a whole load of smaller changes to enable PowerShell to work on Linux and macOS


These changes are in the pipeline
Rename powershell.exe to pwsh.exe - Linux admins don't like typing more than 4 characters at a time evidently
Standarize encoding for cmdlets that write to files
Remove the -ComputerName parameter from many cmdlets e.g. *-Service & *-Process so that individual cmdlet based remoting (over DCOM) isn't available. All remoting goes through SSH or WSMAN


There are also a few issues to consider:

Case sensitivity - Windows is case-insensitive but Linux and macOS are case sensitive. You need to use the correct casing on Linux and mac
File path delimiters - non-Windows must use /
File extensions - not usually used on non-Windows but are required by PowerShell e.g. .ps1 and .psm1
Aliases that match linux commands - ls, cp, mv etc - are removed on Linux and macOS
JEA isn't supported on non-Windows
Snapins aren't available on v6 so some functionality e.g. Active Directory cmdlets can't be used


PowerShell v6 is a major change – probably best regarded as a breaking change. I’ll investigate some of these issues in more depth in subsequent posts


This is a useful list of packages and resources irrespective of version-

PowerShell on Linux

An introduction to PowerShell v6 on Windows, mac and Linux is available here

Well worth a read if you haven’t looked at PowerShell v6 yet

PowerShell v6 beta

PowerShell v6 has reached a significant milestone – the release of the first PowerShell v6 beta version. There have been 18 releases of alpha code since August 2016 when the open source PowerShell v6 project started.

There is no indication of how many beta releases there will be before PowerShell v6 is ready to ship.

Code is available from