PowerShell for Windows Admins

January 28, 2018  8:26 AM

PowerShell –f string

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A PowerShell –f string is used to format the data inside a string. –f is usually referred to as the format operator.

The operation of the format operator is best explained by examples. At its simplest you create fields in the string using {} and the arguments to the right of the –f operator are assigned to those fields in numeric order:

PS> “{0} is  {1}” –f  ‘A’, ‘a’
A is  a

‘A’ is the first argument (so is assigned to field {0} and so on.

You can format the contents of the fields. The full syntax is

{index[,alignment][:format string]}

index is the zero based index of the arguments after the format operator as you’ve seen.

alignment takes a positive number and aligns the item to the right of a field of that length. A negative number produces a left alignment.

PS> “{0,5} is  {1,5}!” -f ‘A’, ‘a’
A is      a!
PS> “{0,-5} is  {1,5}!” -f ‘A’, ‘a’
A     is      a!
PS> “{0,5} is  {1,-5}!” -f ‘A’, ‘a’
A is  a    !
PS> “{0,-5} is  {1,-5}!” -f ‘A’, ‘a’
A     is  a    !

The format strings cover numeric and date time formatting



will get you started and provide links to other formatting information

A few more examples.

To control the total number of digits displayed

PS> “{0:D3} {1:D3} {2:D3}” -f 2, 20, 200
002 020 200

for hexadecimal – case matches case in string

PS> “{0:X4} {1:x8} ” -f  1234, 1234
04D2 000004d2

Truncating the digits after decimal point

PS> “{0:F3} {1:F2} {2:F1}” -f 2.1234, 3.1234, 4.1234
2.123 3.12 4.1

Dates can be manipulated as well

PS> “{0:yyyy} {0:MM} {0:dd} {0:hh} {0:mm} {0:ss}” -f (Get-Date)
2018 01 28 02 24 03

Note that I’m referring to a single object for all of the fields

January 27, 2018  7:09 AM

DSC update

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The PowerShell team have posted an update on what’s happening with DSC. https://blogs.msdn.microsoft.com/powershell/2018/01/26/dsc-planning-update-january-2018/

The interesting thing is the decoupling of the Local Configuration Manager from Windows. A new LCM that can use resources written in multiple languages sounds good – DSC on Linux can finally have custom written resources.

LCM will be open source

No comments on pull server in the post though – ideally pull server should be open source as well

January 26, 2018  7:03 AM

PowerShell v6.0.1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell v6.0.1 is available from https://github.com/PowerShell/PowerShell/releases

This release upgrades PowerShell to use .NET core v2.0.5 which addresses a couple of security vulnerabilities. The release also addresses upgrade issues on some Linux distributions due to version numbers being misunderstood.

Also available is the v1.0.0 beta for OpenSSH https://github.com/PowerShell/Win32-OpenSSH/releases. This version supplies one of my wishes for 2018 in that the installation and configuration is much simpler

January 25, 2018  11:37 AM

Iron Scripter prequels

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

One of the new things for Summit 2018 is the iron Scripter competition on the last afternoon. As a warm up for the competition we’re running a number of Iron Scripter prequels.

A puzzle will be published every week – first 2 are on powershell.org.

A forum exists to discuss the solutions in the context of the Iron Scripter factions.

Even if you aren’t going to Summit you can solve the puzzles and contribute to the solution.

Think of the puzzles as a Scripting Games lite. We provide a commentary on the puzzle including an example solution but we DON’T grade any submissions.

Join in and enjoy.

January 25, 2018  10:21 AM

PowerShell v6 GA and beyond

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell v6 achieved General Availability on 10 January 2018. https://blogs.msdn.microsoft.com/powershell/2018/01/10/powershell-core-6-0-generally-available-ga-and-supported/

Why do these things always happen when I’m in a plane over the Atlantic?

GA is a tremendous milestone but its not the end by any means. Work has already begun on v6.1


Note a service release at the end of January to use .NET core 2.05

V6.1 looks to be planned for about 6 months from now with some interesting features.

January 8, 2018  3:55 AM

Just the date

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Way back in this post https://richardspowershellblog.wordpress.com/2008/03/27/start-and-end-of-week/ I showed how to find the start of the week. I recently had a question about how to restrict the display to just the date.

PowerShell uses the .NET datetime class for working with dates so there will always be time information even if its set to 0. You can however restrict the display to just the date information

The ToShortDateString and ToLongDateString methods will give you just the date information but as a string

PS> $s = Get-Date -Hour 0 -Minute 0 -Second 0
PS> $d = $s.AddDays(-($s).DayOfWeek.value__)
PS> $d.ToShortDateString()
PS> $d.ToLongDateString()
07 January 2018

Alternately you could create a custom format using the formatting strings found at


For example

PS> Get-Date -Date $d -Format “yyyy-MM-dd gg”
2018-01-07 A.D.

You could combine the code lines to give

PS> $s = Get-Date -Hour 0 -Minute 0 -Second 0
PS> Get-Date -Date ($s.AddDays(-($s).DayOfWeek.Value__)) -Format “yyyy-MM-dd gg”
2018-01-07 A.D.

If you do this often enough then create a function

January 4, 2018  2:44 PM

Relevance of Scripts

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Books, Powershell

I had a sudden thought today about the relevance of scripts – PowerShell Scripts –  today.

PowerShell v6 can’t run some of the modules that we’ve come to rely on – for instance the AD cmdlets. The Windows Compatibility Pack (see previous post) enables access to some of the underlying .NET classes that enable AD administration through PowerShell.

This means going back to the v1/v2 days and writing scripts – we may wrap them as advanced functions and modules these days but the basic code is the same – instead of using canned cmdlets.

My first two books

PowerShell in Practice – https://www.manning.com/books/powershell-in-practice


PowerShell and WMI – https://www.manning.com/books/powershell-and-wmi

supply lots of code examples for working with PowerShell Scripts including AD and WMI. If you haven’t got a copy they’ll help you get back to basics.

January 4, 2018  8:45 AM

Windows Compatibility Pack

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, Powershell

As reported last month the Windows Compatibility Pack for .NET core is available. This adds back some of the functionality missing from .NET core. This functionality is ONLY of relevance on Windows machines.

A PowerShell module based on the Compatibility Pack is in the works – this will add a number of cmdlets including the WMI cmdlets back into PowerShell v6 on Windows. There’s no ETA on the module at this time.

There is a module on the PowerShell gallery that will add the .NET components of the Compatibility Pack into your PowerShell v6 session.

PS>  Find-Module -Name PSCoreWindowsCompat | ft -a

Version Name                Repository Description
------- ----                ---------- ----------- PSCoreWindowsCompat PSGallery  Provides the Microsoft.Windows.Compatibility Pack to PowerShell Core.

If you want to inspect the module

PS>  Save-Module -Name PSCoreWindowsCompat -Repository PSGallery -Path C:\Source\ -Force

To install the module:

PS>  Install-Module -Name PSCoreWindowsCompat -Repository PSGallery -Verbose -Force
 VERBOSE: Repository details, Name = 'PSGallery', Location = 'https://www.powershellgallery.com/api/v2/'; IsTrusted = 'False'; IsRegistered = 'True'.
 VERBOSE: Using the provider 'PowerShellGet' for searching packages.
 VERBOSE: Using the specified source names : 'PSGallery'.
 VERBOSE: Getting the provider object for the PackageManagement Provider 'NuGet'.
 VERBOSE: The specified Location is 'https://www.powershellgallery.com/api/v2/' and PackageManagementProvider is 'NuGet'.
 VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PSCoreWindowsCompat'' for ''.
 VERBOSE: Total package yield:'1' for the specified package 'PSCoreWindowsCompat'.
 VERBOSE: Performing the operation "Install-Module" on target "Version '' of module 'PSCoreWindowsCompat'".
 VERBOSE: The installation scope is specified to be 'AllUsers'.
 VERBOSE: The specified module will be installed in 'C:\Program Files\PowerShell\Modules'.
 VERBOSE: The specified Location is 'NuGet' and PackageManagementProvider is 'NuGet'.
 VERBOSE: Downloading module 'PSCoreWindowsCompat' with version '' from the repository 'https://www.powershellgallery.com/api/v2/'.
 VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PSCoreWindowsCompat'' for ''.
 VERBOSE: InstallPackage' - name='PSCoreWindowsCompat', version='',destination='C:\Users\Richard.MANTICORE\AppData\Local\Temp\51711061'
 VERBOSE: DownloadPackage' - name='PSCoreWindowsCompat', version='',destination='C:\Users\Richard.MANTICORE\AppData\Local\Temp\51711061\PSCoreWindowsCompat\PSCoreWindowsCompat.nupkg', uri='https://www.powershellgallery.com/api/v2/package/PSCoreWindowsCompat/'
 VERBOSE: Downloading 'https://www.powershellgallery.com/api/v2/package/PSCoreWindowsCompat/'.
 VERBOSE: Completed downloading 'https://www.powershellgallery.com/api/v2/package/PSCoreWindowsCompat/'.
 VERBOSE: Completed downloading 'PSCoreWindowsCompat'.
 VERBOSE: InstallPackageLocal' - name='PSCoreWindowsCompat', version='',destination='C:\Users\Richard.MANTICORE\AppData\Local\Temp\51711061'
 VERBOSE: Catalog file 'PSCoreWindowsCompat.cat' is not found in the contents of the module 'PSCoreWindowsCompat' being installed.
 VERBOSE: Module 'PSCoreWindowsCompat' was installed successfully to path 'C:\Program Files\PowerShell\Modules\PSCoreWindowsCompat\'.

Notice the installation path is OUTSIDE of the current version of PowerShell v6 so should remain available through any upgrades.

PS>  Import-Module -Name PSCoreWindowsCompat

Now you’ve got it how do you use it? The module DOESN’T have any functions – it just loads the .NET namespaces.

Its back to PowerShell v1 days – everything is a script instead of a cmdlet. For instance the Compatibility pack contains the System.DirectoryServices so you can script against AD.

Let’s say you want to see all the users in the domain:

$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
 $root = $dom.GetDirectoryEntry()

$search = [System.DirectoryServices.DirectorySearcher]$root
 $search.Filter = "(&(objectclass=user)(objectcategory=user))"
 $search.SizeLimit = 3000
 $result = $search.FindAll()

foreach ($user in $result){

Use System.DirectoryServices.ActiveDirectory.Domain to get the current domain. Create a System.DirectoryServices.DirectorySearcher object and set the filter to users. Find all of the users and display their distinguishedname

Its a lot more complicated than using the cmdlet:

PS>  Get-ADUser -Filter * | select DistinguishedName

but it gets the job done.

If you need to administer AD and you need the cross platform capabilities of PowerShell maybe you should use the  PSCoreWindowsCompat module (with aplogies to A-Team fans everywhere)

January 3, 2018  12:37 PM

PowerShell arrays

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

An array is a collection of objects. PowerShell arrays can be created manually

PS> $a = 1,2,3,4


$b = @(1,2,3,4)

PowerShell will also create arrays automatically when needed:

PS> $ps = Get-Process

All three options are arrays:

PS> $a.GetType()

IsPublic  IsSerial  Name     BaseType
 -------- --------  ----     --------
 True     True      Object[] System.Array

PS> $b.GetType()

IsPublic  IsSerial Name     BaseType
 -------- -------- ----     --------
 True     True     Object[] System.Array

PS> $ps.GetType()

IsPublic  IsSerial Name     BaseType
 -------- -------- ----     --------
 True     True     Object[] System.Array

The individual elements in an array are accessed using an index that starts at 0

PS> $a[0]

You can use a range of indices

PS> $a[1..2]

You can use negative indices to count from the end of the array

PS> $a[-1]

PS> $a[-1..-2]

PowerShell arrays are polymorphic by default meaning you can store any type of object in an array – and can store multiple types of objects in a single array

PS> $a += ‘Hello World’

PS> $a
Hello World

We haven’t actually extended the array – a new array is created that contains the old array and the new element. Any time you find yourself adding elements to an array in a loop – STOP and think about how you could do this as a pipeline.

PS> $x = @()
PS> 1..5 | foreach {$x += $_}
PS> $x -join ‘ ‘
1 2 3 4 5

is very inefficient compared to

PS> $y = 1..5 | foreach {$_}
PS> $y -join ‘ ‘
1 2 3 4 5

As you saw earlier you can add elements to an existing array. You can also remove elements from an array:

PS> $a = $a -ne 3
PS> $a
Hello World

Iterating over the contents of an array is as simple as

PS> $a | foreach {$_}


PS> foreach ($i in $a){$i}

PowerShell arrays are powerful tools that can make your coding much easier. This post has covered the most likely tasks you’ll face using arrays in PowerShell

December 31, 2017  2:30 PM

PowerShell in 2018

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

So what is going to happen for PowerShell in 2018?

In April we have the Summit. Our biggest ever Summit with many more speakers, more sessions and new things including Iron Scripter. We’ll be starting the build up in early January so keep an eye on powershell.org.

PowerShell v6 will be GA in January. This is the point where you have decisions to make. Do you ignore v6; try and use v6 only or attempt some kind of dual use. Only your needs can answer what is the right solution for you but multiple PowerShell versions combined with multiple versions of Windows server – there’ll be feature updates in Match and September if plans remain the same – will definitely raise complications.

What should you be doing in 2018?

If you haven’t booked a Summit place and want to go then don’t be too late in registering. Sales have been much faster than last year and I suspect we’ll sell out early in 2018. We will have another batch of places available on alumni discount in January.

The Windows compatibility pack for .NET core (still seems ironic that’s its needed) will become available. That will plug some, but not all, of the gaps in functionality between v6 and v5.1. I’d recommend learning, or possibly re-learning, how to write scripts using System.DirectoryServices as it seems likely to be the only way to administer AD from v6 in the near future.

If you haven’t evaluated v6 then do so – side by side install with v5.1 makes that easier.

If you follow the PowerShell project on github you’ll see that v6.1 is already under discussion. I’d recommend that you join the discussion and help shape the future of PowerShell.

What would I like to see in 2018?

All the Windows inbuilt and RSAT modules modified to work with v6.

A simple and effective way to install and configure OpenSSH for PowerShell remoting on Windows – without having to install chocolaty or other third party features

A good set of cmdlets for managing containers

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: