PowerShell for Windows Admins

May 25, 2019  12:00 PM

OpenSSH installation

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
OpenSSH, Powershell

OpenSSH installation has got a lot simpler in Windows 10 1809; Windows Server 2019 and Windows Server 1809.

OpenSSH is available as an optional feature. The client is preinstalled when you install the operating system. You just need to install the server:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~

Installing the optional feature creates the required firewall rule which is good.

You still need to make changes to the sshd_config file to enable password and pubkey authentication. The subsystem isn’t configured for PowerShell.

There’s a bug in OpenSSH so that subsystem paths with spaces aren’t parsed so you need to create a symbolic link for the PowerShell v6 folder.

if you want to use key-pair authentication the OpenSSHUtils module on the PowerShell gallery has bugs so you need to manually set the permissions on the authorized_keys file.

SSH remoting has a lot to offer but incorrect documentation, the work needed to install and configure it and buggy software will stop people using it. On the plus side OpenSSH is getting easier to install and configure but its still a long way from good.

May 23, 2019  1:20 PM

Create a symbolic link

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I recently had to create a symbolic link to overcome a bug in OpenSSH whereby OPENSSH won’t work with the path C:\Program Files\PowerShell\6\pwsh.exe because it has a space.

The answer is to create a symbolic link which is a file that contains a reference to another file (or directory):

New-Item -ItemType SymbolicLink -Path C:\pwsh -Target ‘C:\Program Files\PowerShell\6’

C:\pwsh is the symbolic link and the Target parameter has the original path. You can now use C:\pwsh in place of C:\Program Files\PowerShell\6

New-Item can also create a Hardlink or a Junction.

HardLink is a directory entry that associates a name with a file on disk

Junction is an NTFS artefact that is a pointer to a directory on the local volume

May 21, 2019  12:26 PM

PowerShell Core v6.2.1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell Core v6.2.1 has been released – https://github.com/PowerShell/PowerShell/releases

as has v6.1.4

The new versions are to primarily fix the Security Vulnerability CVE-2019-0733 – https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0733

v6.2.1 also enables tab completion for functions

May 19, 2019  12:56 PM

Windows Server 2019 updates with CIM

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell

Windows Server 2019 updates with CIM remain the same as all server versions post Windows Server 2016. This code will check for and install any updates. Micorosft Update or WSUS will be used depending on how your system is configured

$au = Invoke-CimMethod -Namespace root/microsoft/windows/windowsupdate -ClassName MSFT_WUOperations -MethodName ScanForUpdates -Arguments @{SearchCriteria=”IsInstalled=0″}

if ($au.Updates.Length -gt 0) {
Invoke-CimMethod -Namespace root/microsoft/windows/windowsupdate -ClassName MSFT_WUOperations -MethodName InstallUpdates -Arguments @{Updates = $au.Updates}
else {
Write-Warning “No updates available”

This code should work on Server 1709, 1803, 1809 and Windows Server 2019.

It won’t work on Windows Server 2016 as the CIM classes were changed post Windows Server 2016

May 19, 2019  12:46 PM

WSL improvements

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

Windows Subsystem for Linux – WSL improvements have been recently announced – https://devblogs.microsoft.com/commandline/

WSL 2 is on the way which will allow more Linux apps in WSL including Docker

A Linux kernel will ship with Windows especially tuned for WSL 2

WSL 2 will be much faster and have full system call compatibility.

A new console – now called a Terminal (more Linux terminology) will also become available for WSL, Windows Command prompt and most importantly PowerShell. It’ll feature multiple tabs

Windows Terminal will be shipped via the Windows Store  – do I really want to access an online Store for server software?

May 6, 2019  1:02 PM

Modifying hashtables

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Saw a question about modifying hashtables. The suggested code seemed like overkill.

The starting point is this hashtable:

$record = @{Name=’Joe’; Date=’2019-02-01′; Status=’Pending’}

The updated data is:
$update = @{Name=’Joe’; Date=’2019-04-01′; Status=’Hired’; City=’York’; Country=’England’}

You need to keep the Name and Date from $record. Modify the Status to be that of $update and add the City and County information to record.

Changing status is a simple assignment:

$record.Status = $update.Status

Adding the City and County information is done by adding them to the original hashtable.

$record += @{City=$update.City; Country=$update.Country}

You can check the results by displaying the hashtable.

Technically, you’re creating a new hashtable, adding the information from $record and then the City and Country information but as it stays in the original variable its always referred to as modifying.

April 30, 2019  3:06 PM

PowerShell SSH

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell SSH support is available by default in PowerShell v6.0 and later. The big thing for PowerShell v6.0 was SSH based remoting.

On Windows 10 / Server 2019 OpenSSH is available as an optional install. On earlier versions of Windows you need to install OpenSSH – https://github.com/PowerShell/openssh-portable

The installation instructions are available at


If you’re still using Windows PowerShell and need SSH support consider


I think SSH remoting should be considered a must learn as its ideal for non-domain remoting situations and avoids the need for certificates in non-domain scenarios.

April 30, 2019  1:48 PM


Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Count is a property on arrays

PS> $x = 1..10
PS> $x.Count

The same information is available through Length (which is the property in the System.Array class definition)

PS> $x.Length

If the variable is a scalar you get 1 returned

PS> $x = 1
PS> $x.Count

With an empty array you get zero returned

PS> $x = @()
PS> $x.Count

This means that however many items are in the array you can safely check the number of items.

Be careful with strings as Count and Length give different results

PS> $x = ‘asdfghjkl;’
PS> $x.count
PS> $x.length

If you want to test the number of elements returned use Count rather than length

April 30, 2019  7:01 AM

Where-Object options

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

You have a few Where-Object options when you want to filter data. Remember that Where-Object filters objects based on property values and Select-Object filters objects based on object position in the pipeline or array as well as filtering properties.

The classic way to use Where-Object is to use a filter script

PS> Get-Process | Where-Object -FilterScript {$_.CPU -gt 5}

You’re filtering to accept process objects where the CPU property shows more than 5 seconds of usage

As an aside most people don’t use the FilterScript parameter they rely on positional parameters to assign the script block to FilterScript. Script analysers such as PSScriptAnalyzer (at least as far as the rules in VScode are concerned) don’t seem to object to the use of positional parameters in this case which is rather sloppy and remiss. Another reason I don’t like any of the analysis tools I’ve tried as they aren’t consistent.

PowerShell then introduced a simpler syntax

PS> Get-Process | Where-Object -Property CPU -gt -Value 5

which is usually used via positional parameters

PS> Get-Process | Where-Object CPU -gt 5

which again seems to sneak past the analysers. If you want multiple clauses in the filter using –and / –or to join them you have to use the original syntax. Also note that –gt isn’t an operator – its a parameter!

The is also the little used array method option to filter a collection of objects

PS> (Get-Process).Where({$_.CPU -gt 5})

which it should be noted is much faster than Where-Object on the pipeline.

When using Where-Object remember the options and if you’re using positional parameters remember what you’re actually doing.

April 29, 2019  1:52 PM

Opposing Automation

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Philosophy, Powershell

Opposing Automation – no I don’t mean that you should oppose it. The sad fact is that there are very many administrators opposed to automation.

Within two hours of starting my last job I was told by my team lead “you’ll never automate anything here”. Needless to say our relationship never really worked after that. I ended up in a different team and yes I did automate a lot of stuff.

Other all time favourites of mine are:

“We’re too busy to automate”

“We’ve always done it this way”

If you meet real roadblocks like this you’ll more than likely end up looking for another job.

There are a few things you can try though.

In your own work try automating tasks that take a long time and very repetitive for example one company insisted on the event logs being checked for specific events on a regular basis. Now, the idea solution would be a monitoring solution but that means spending money… One solution is to RDP into all the boxes and query the event logs. On the other hand a quick script that remotes into the required servers and checks the logs. Report the date and time of the events by server and you’re done. Better still schedule the task for overnight and you don’t need to do much at all once its set up. Even if you have to create the functionality in chunks its surprising how quickly you can build up to a useful set of utilities. Don’t forget – automate what you need not what the books (including mine) suggest – you’re the one how knows what you need.

The other approach that can sometimes work is to find how you can help someone else get something done. Again you may need to build the functionality in chunks but getting other people to sell the benefits of automation will be a big help.

However, you approach the problem there will always be people opposed to automation – your only options are to work round them or to move somewhere where your ideas are appreciated. Don’t stay and suffer – its not worth it.

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: