Monthly Archive


PowerShell v6

New releases of PowerShell v6.x

New releases of PowerShell v6.x are available.

First off v6.0.3 is available. This is a servicing release to update PowerShell v6.0 to use .Net 2.0.8. The primary point of this release is to update to fix the vulnerability discussed in Microsoft Security Advisory CVE-2018-8356: .NET Framework Security Feature Bypass Vulnerability. You ae recommended to upgrade PowerShell v6.0.x to v6.0.3


Secondly, preview 4 for Powershell v6.1 is also available. It has some breaking changes:

Visualbasic support is removed from Add-Type

PowerShell direct tries PowerShell v6.x then drops back to PowerShell v5.1

Powershell v6.1 can start in a folder with a wildcard in its name

Enable-PSRemoting produces configuration names unique for preview releases

CompatiblePSeditions check is enforced for modules from system32 module path (PowerShell v5.1 modules!)



Experimental features are supported

Markdown rendering cmdlets are available

ThreadJob module available

WMI and ADSI accelerators are back


Plus a bunch of minor updates you can see in the release notes

Both releases are available from


PowerShell v6.1 preview 3

PowerShell v6.1 preview 3 became available a couple of weeks ago.

To the user its a minor set of fixes from preview 2 though if you read the release notes there’s a lot of work going on in the background.

If the 6 months between releases idea holds we can expect to see the v6.1 release within the next month.

OpenSSH is still a bit of a mess with options to install some, or all, as Windows optional features or install from the github project. This needs to be sorted with definitive guidelines a preferably a roadmap.

PowerShell version

Discovering the PowerShell version you’re using can be an interesting task.

The automatic variable $PSVersionTable was introduced in PowerShell v2. On my Windows 10 version 1803 machine for Windows PowerShell I get

PS> $PSVersionTable

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


$PSVersionTable is a hashtable so the order in which items are displayed may vary. The contents of the hashtable have changed over time as well.


The important parts of $PsversionTable include:

The version of PowerShell itself

PS> $PSVersionTable.PSVersion

Major Minor Build Revision
----- ----- ----- --------
5 1 17134 48

PS> $PSVersionTable.PSVersion.Major

This a simple test for version.


The edition is also important

PS> $PSVersionTable.PSEdition

Desktop means its full CLR – in other words Windows PowerShell


The WSMAN version is also important

PS> $PSVersionTable.WSManStackVersion

Major Minor Build Revision
----- ----- ----- --------
3 0 -1 -1

You need v3 to use CIM sessions.


With PowerShell v6 you get a few more options

PS> $PSVersionTable

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


Notice PSEdition is set to Core.

The OS and Platform data are v6 only

The PSRemotingProtocolVersion, SerializationVersion and WSManStackVersion are the same for Windows PowerShell v5.1 and PowerShell v6.


PowerShell v6 runs on Windows, Linux and macOS. You can test which OS you’re on from $PSVersionTable or more simply using the following automatic variables:

PS> ls variable:\is*

Name Value
---- -----
IsLinux False
IsMacOS False
IsWindows True
IsCoreCLR True

Using these you could create branching logic to perform a task by calling the appropriate command based on the underlying operating system.

Format Data

PowerShell will format the output of objects that it knows about. For instance Get-Process shows different sets of properties depending on whether you choose a table or list view. The format data is stored in files named *.format.ps1xml.

In Windows PowerShell the format files are found in C:\Windows\System32\WindowsPowerShell\v1.0. In PowerShell v6 the format files are stored with the appropriate module.


If you want to create formatting for a new object, or change the formatting for an existing object the best place to start is to export the format data for an existing object

Get-FormatData -TypeName System.Diagnostics.Process | Export-FormatData -Path f5.txt

gets the format data for the object used in Get-Process.

The drawback is that is presented a long string

<?xml version="1.0" encoding="utf-8"?><Configuration><ViewDefinitions><View><Name>process</Name><ViewSelectedBy><TypeNam
th><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader /></TableHeaders><TableRowEntries><TableRowEntry><


And you have to manage the pretty printing yourself.

In PowerShell v6.1 the output is automatically pretty printed

Get-FormatData -TypeName System.Diagnostics.Process | Export-FormatData -Path f6.txt

<?xml version="1.0" encoding="utf-8"?>
<TableColumnHeader />


which makes it much easier to work with

where –not

PowerShell v6.1 preview 2 has added the where –not option.

The option adds another parameter to the syntax

where-object <property name> <operator like parameter> <value>


Couple of examples of using the syntax

Get-Process | where CPU -gt 12

Get-Service | where Status -like 'Stop*'


Use –Not when you’re looking for properties that aren’t set. For example

Get-Service | where -Not DependentServices


Get-Process | where -Not StartTime

Calculating standard deviation

Calculating a standard deviation isn’t a difficult exercise but PowerShell v6.1 offers an easier method.


In Windows PowerShell v5.1 and PowerShell v6.0 the Measure-Object cmdlet has this syntax

PS> Get-Command Measure-Object -Syntax

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-Sum] [-Average] [-Maximum] [-Minimum] [<CommonParameters>]

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-Line] [-Word] [-Character] [-IgnoreWhiteSpace] [<CommonParameters>]


In PowerShell v6.1.0-preview.2 this changes to

PS> Get-Command Measure-Object -Syntax

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-StandardDeviation] [-Sum] [-Average] [-Maximum] [-Minimum] [<CommonParameters>]

Measure-Object [[-Property] <string[]>] [-InputObject <psobject>] [-Line] [-Word] [-Character] [-IgnoreWhiteSpace] [<CommonParameters>]


You’ve now got a standard deviation option.

How do you use it?

PS> 1..517 | Measure-Object -Sum -Average -StandardDeviation

Count : 517
Average : 259
Sum : 133903
Maximum :
Minimum :
StandardDeviation : 149.389312424506
Property :


There’s probably a few other calculations that would be useful to add to Measure-Object

PowerShell v6.1 Range Operator

The PowerShell v6.1 Rang Operator has been enhanced to deal with letters as well as numbers.

The range operator has always been available in PowerShell. It can be used to generate a range of integers for example:

PS>  (1..10) -join ','
PS>  (10..1) -join ','
PS>  (-10..10) -join ','
PS>  (10..-10) -join ','


In PowerShell v6.1 the range operator can also produce sequences of letters

PS>  'a'..'z' -join ','
PS>  'z'..'a' -join ','

PS>  'A'..'Z' -join ','
PS>  'Z'..'A' -join ','


Be careful with mixing case

PS>  'Z'..'a' -join ','
PS>  'a'..'Z' -join ','
PS>  'z'..'A' -join ','
PS>  'A'..'z' -join ','


As you might get more than you wanted  🙂

Installing PowerShell v6.1 preview 2

The MSI for installing PowerShell v6.1 preview 2 has a screen for optional actions:

Add PowerShell to Path environment variable
Register Windows Event Logging Manifest
Enable PowerShell remoting
Add 'open here' context menus to Explorer


The 6.1 preview installs side by side with PowerShell v6.0.x


Test-Connection in v6.1

PS> Get-Command Test-Connection -Syntax

Test-Connection [-TargetName] <string[]> [-Ping] [-IPv4] [-IPv6] [-ResolveDestination] [-Source <string>] [-MaxHops <int>] [-Count <int>] [-Delay <int>] [
-BufferSize <int>] [-DontFragment] [-TimeoutSeconds <int>] [-Quiet] [<CommonParameters>]

Test-Connection [-TargetName] <string[]> [-Ping] [-IPv4] [-IPv6] [-ResolveDestination] [-Source <string>] [-MaxHops <int>] [-Delay <int>] [-BufferSize <int>] [-DontFragment] [-Continues] [-TimeoutSeconds <int>] [-Quiet] [<CommonParameters>]

Test-Connection [-TargetName] <string[]> -MTUSizeDetect [-IPv4] [-IPv6] [-ResolveDestination] [-TimeoutSeconds <int>] [-Quiet] [<CommonParameters>]

Test-Connection [-TargetName] <string[]> -Traceroute [-IPv4] [-IPv6] [-ResolveDestination] [-Source <string>] [-MaxHops <int>] [-TimeoutSeconds <int>] [-Quiet] [<CommonParameters>]

Test-Connection [-TargetName] <string[]> -TCPPort <int> [-IPv4] [-IPv6] [-ResolveDestination] [-Source <string>] [-TimeoutSeconds <int>] [-Quiet] [<Common

is very different to Test-Connection in v5.1

Test-Connection [-ComputerName] <string[]> [-AsJob] [-DcomAuthentication <AuthenticationLevel>] [-WsmanAuthentication <s
tring>] [-Protocol <string>] [-BufferSize <int>] [-Count <int>] [-Impersonation <ImpersonationLevel>] [-ThrottleLimit <i
nt>] [-TimeToLive <int>] [-Delay <int>] [<CommonParameters>]

Test-Connection [-ComputerName] <string[]> [-Source] <string[]> [-AsJob] [-DcomAuthentication <AuthenticationLevel>] [-W
smanAuthentication <string>] [-Protocol <string>] [-BufferSize <int>] [-Count <int>] [-Credential <pscredential>] [-Impe
rsonation <ImpersonationLevel>] [-ThrottleLimit <int>] [-TimeToLive <int>] [-Delay <int>] [<CommonParameters>]

Test-Connection [-ComputerName] <string[]> [-DcomAuthentication <AuthenticationLevel>] [-WsmanAuthentication <string>] [
-Protocol <string>] [-BufferSize <int>] [-Count <int>] [-Impersonation <ImpersonationLevel>] [-TimeToLive <int>] [-Delay
<int>] [-Quiet] [<CommonParameters>]


You’ll need to experiment to see the differences and to determine which works best for you.


Test –json I’m not sure if its working correctly or not – it throws an exception with a JSON file I’ve used many times and also with this

PS> Get-Process p* | ConvertTo-Json | Test-Json
Test-Json : Cannot parse the JSON.
At line:1 char:35
+ Get-Process p* | ConvertTo-Json | Test-Json
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: ([
]:String) [Test-Json], Exception
+ FullyQualifiedErrorId : InvalidJson,Microsoft.PowerShell.Commands.TestJsonCommand

needs some investigation.

PowerShell v6.1 preview 2

PowerShell v6.1 preview 2 is now available for download from


The breaking changes shouldn’t affect your code as they’re for telemetry and installation


Test-Connection is now available in v6

Export-FormatData will pretty print the XML rather than just giving you a single string

There’s now a Test-Json cmdlet and a –Not parameter has been added to Where-Object


OpenSSH has moved to but releases are managed through

Confused? So am I.

This may be linked to the fact that OpenSSH is appearing as an optional install in Windows 10 and Windows Server (post v1709) though the server only had the option for the client last time I looked.

The OpenSSH story is becoming more confusing every time I look at it. It needs to be sorted if remoting between Linux and Windows is to become a thing.


Installing Win32 OpenSSH

I’ve had a number problems Installing Win32 OpenSSH since it became available and required for SSH based remoting in PowerShell v6


Every time I install a new version the instructions have changed. Admittedly the installation is getting easier BUT as the project is still producing beta versions then installing over the top of an existing installation has been necessary and that’s where the problems occur.


Every time I’ve tried to upgrade Win32 OpenSSH I’ve had problems. I’ve come to the conclusion that the best thing to do is to completely remove the old version of OpenSSH and then re-install from scratch. Save the old config file as an easy way to get your configuration back.


OpenSSH is needed for remoting to/from Linux systems and is useful for remoting to non-domain machines. There needs to be a very simple install, configuration and update process that DOESN’T involve messing about with chocolately packages or the ever changing install instructions.