Monthly Archive


Monthly Archives: June 2016

Wireless on Windows 2016 TP5

Windows Server 2016 TP5 which appeared at the end of April has a major flaw. It doesn’t work with wireless cards!


I use a relatively high-spec laptop as my lab machine. Not being able to get the wireless card working means no Internet access and makes activation a lot more difficult.


The June Cumulative Update KB3163016 appears to fix the issue.


Install Windows 2016 TP5. Then immediately install KB3163016. Install the Wireless LAN Service (needs a reboot) through Add Roles and features or

Add-WindowsFeature –Name Wireless-Networking


The Wireless LAN Service defaults to disabled so you’ll need to change the start type to automatic and start the service.


Then you can install whatever Windows features you need.


One thing I’ve noticed is that the wireless card doesn’t seem to keep its connection to the wireless network between reboots. Its an annoyance in a TP would be beyond aggravating in final version

Cleaning up entries on Remote Desktop Connection

I use RDP between my main laptop and the machine on which my lab resides. When I rebuild the lab the entries in the Remote Desktop Connection for the old machine still remain.


There isn’t a direct way to remove those entries. But you can remove them from the registry.


First view the entries

Get-ChildItem -Path 'HKCU:\SOFTWARE\Microsoft\Terminal Server Client\'

    Hive: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal Server Client

Name                           Property
----                           --------
Default                        MRU0 : RSLaptop01
                               MRU1 : serverrs01
                               MRU2 : server02


The partial list above shows you that the property names are MRU* 


You can view individual entries

Get-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Terminal Server Client\Default\' -Name MRU2

MRU2         : server02
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal
               Server Client\Default\
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal
               Server Client
PSChildName  : Default
PSDrive      : HKCU
PSProvider   : Microsoft.PowerShell.Core\Registry


You can now delete as required – for instance


Remove-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Terminal Server Client\Default\' -Name MRU2

Boolean in Where-Object filter

I was testing some code yesterday and realised there was a quirk in the way the original where syntax (with {}) worked and the way the newer syntax worked.


To demonstrate this I created a set of objects

$i = 0

$tests = while ($i -lt 25){
  New-Object -TypeName PSObject -Property @{
    Index = $i
    Current = if (-not($i % 2)){$true} else {$false}


Object properties are a numeric index and a boolean value


If you want just the $true values many people write this

$tests | where {$_.Current -eq $true}


or if using the newer syntax use this

$tests | where Current -eq $true


This is unnecessary typing as you can do this

$tests | where {$_.Current}

$tests | where Current


The reason is that the filter you are creating tests a property of the current object against your criteria and passes is if the result is true. A boolean property will by definition either be true of false so just need to test directly


if you want to double negative type test i.e. – not $true (which I don’t recommend as its very easy to get into  logic mess) then you have to do this

$tests | where {-not $_.Current}


as this fails
$tests | where –not Current


You could do this

$tests | where Current -ne $true


but it negates the whole code simplification objective

Still asking for topics

Earlier in the month I posted a request for topics on


This is a request for YOU to tell us what topics you would like to see at the next PowerShell & DevOps Summit


We’ve had a handful of replies so far.


This is your chance to influence the content of the Summit. These topics will be included as suggestions in the Call for Proposals where we ask potential speakers to send us their session proposals. That will be going out next month.


if there is something in the PowerShell/DevOps world you want to know more about let us know.

PowerShell Summit & Conference videos 2016


If you didn’t get to any of these conferences this year the videos are now available.


PowerShell and DevOps Summit


European PowerShell Conference


You might find this interesting as well.

WinOps conference

Too many Windows 10 releases????????

The last couple of days have seen some incredibly stupid headlines but one that caught my eye was someone from the “computer press” whining that there are too many releases of Windows 10.




What part of the Windows Insider Preview program does this person not understand?


You have to sign up to get Windows Insider Previews!


You have a choice of the fast ring (all releases) or the slow ring (fewer releases).


if you don’t want new releases take your self off the program!


Bet we’d get whines that Microsoft wasn’t doing enough releases if they went back to 1 every three or more years.


Complain about technical problems by all means but something you signed up to do!


Needless to say I’ve dropped that feed

Parallel processing

One of the great features PowerShell brings is the ability to remotely administer your servers. Most people begin remote administration by processing the servers sequentially. Eventually, this process breaks down because you have too many servers and/or the processes you are running against each server are long running.


At this point you have to consider parallel processing.


The UK TechNet blog has recently published my article on the options for parallel processing using various PowerShell techniques


It would be nice to be able to do this:

PS>  Get-Date -Day 25 -Month December -Year 2016
Get-Date : Cannot bind parameter 'Month'. Cannot convert value "December" to type "System.Int32".
Error: "Input string was not in a correct format."
At line:1 char:25
+ Get-Date -Day 25 -Month December -Year 2016
+                         ~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCo


You have to do this:

PS>  Get-Date -Day 25 -Month 12 -Year 2016

25 December 2016 11:00:56


The time is set to current time automatically.


One of the gaps in .NET is an enum for the months of the year. You get an enum for days of the week:

PS>  [System.DayOfWeek]::Friday


PS>  0..6 | foreach {[System.DayOfWeek]$psitem}


PowerShell v5 gives you the capability to make your own enums:

enum MonthsOfYear {
January = 1
February = 2
March = 3
April = 4
May = 5
June = 6
July = 7
August = 8
September = 9
October = 10
November = 11
December = 12


PS>  [MonthsOfYear]10

PS>  [MonthsOfYear]::April


PS>  1..12 | foreach {[MonthsoFYear]$PSItem}


PS>  [System.Enum]::GetNames([MonthsOfYear])


Now you can use the name of the month

PS>  Get-Date -Day 25 -Month ([MonthsOfYear]::December) -Year 2016

25 December 2016 11:19:38


Enums are one of those pieces of functionality that you don’t necessarily think about but are very useful. The ability to create your own in PowerShell is very useful and will become more widespread as people realise its available.

WMI classes and Storage cmdlets

There is a hierarchy of objects to work through when dealing with disks

First you have the physical disk

PS>  Get-CimInstance -ClassName Win32_DiskDrive | fl

Partitions : 5
Model      : HFS256G3AMNB-2200A
Size       : 256052966400
Caption    : HFS256G3AMNB-2200A


A physical disk can have 1 or more partitions:

PS>  Get-CimInstance -ClassName Win32_DiskPartition | fl

NumberOfBlocks   : 716800
BootPartition    : False
Name             : Disk #0, Partition #0
PrimaryPartition : False
Size             : 367001600
Index            : 0


NumberOfBlocks   : 409600
BootPartition    : True
Name             : Disk #0, Partition #1
PrimaryPartition : True
Size             : 209715200
Index            : 1


NumberOfBlocks   : 485312512
BootPartition    : False
Name             : Disk #0, Partition #2
PrimaryPartition : True
Size             : 248480006144
Index            : 2


NumberOfBlocks   : 921600
BootPartition    : False
Name             : Disk #0, Partition #3
PrimaryPartition : False
Size             : 471859200
Index            : 3


NumberOfBlocks   : 12492800
BootPartition    : False
Name             : Disk #0, Partition #4
PrimaryPartition : False
Size             : 6396313600
Index            : 4


next step down is logical disks

PS>  Get-CimInstance -ClassName Win32_LogicalDisk | fl

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 108900372480
Size         : 248480002048
VolumeName   : Windows


The classes Win32_DiskDriveToDiskPartition and Win32_LogicalDiskToPartition  link physical disks to partitions and partitions to logical disks respectively.


Then you’ve got volumes – which is where you actually work with disks for the most part

PS>  Get-CimInstance -ClassName Win32_Volume | fl Caption, Label

Caption : C:\
Label   : Windows


Caption : \\?\Volume{524b798f-a072-4ecc-8cfe-fb823e10a5e7}\
Label   : Windows RE tools


Caption : \\?\Volume{4ea44e2e-dd30-4cd9-bfd1-c991be836d97}\
Label   :


Caption : \\?\Volume{c671d23c-f5e5-473d-b6c4-fecb4a99e5b3}\
Label   : Recovery image


The Storage module introduced with Windows 8 has cmdlets for some of these tasks:

PS>  Get-PhysicalDisk | fl FriendlyName, SerialNumber, CanPool, OperationalStatus, HealthStatus, Usage
, Size

FriendlyName      : HFS256G3AMNB-2200A
SerialNumber      : EI3AN118813AM3740
CanPool           : False
OperationalStatus : OK
HealthStatus      : Healthy
Usage             : Auto-Select
Size              : 256060514304



PS>  Get-Partition | fl PartitionNumber, DriveLetter, Offset, Size, Type

PartitionNumber : 1
DriveLetter     :
Offset          : 1048576
Size            : 367001600
Type            : Recovery


PartitionNumber : 2
DriveLetter     :
Offset          : 368050176
Size            : 209715200
Type            : System


PartitionNumber : 3
DriveLetter     :
Offset          : 577765376
Size            : 134217728
Type            : Reserved


PartitionNumber : 4
DriveLetter     : C
Offset          : 711983104
Size            : 248480006144
Type            : Basic


PartitionNumber : 5
DriveLetter     :
Offset          : 249191989248
Size            : 471859200
Type            : Recovery


PartitionNumber : 6
DriveLetter     :
Offset          : 249663848448
Size            : 6396313600
Type            : Recovery


Get-Disk returns similar, but not identical, information to Get-PhysicalDisk


The Get-Disk cmdlet gets one or more Disk objects visible to the operating system, or optionally a filtered list.

The Get-Disk cmdlet gets one or more Disk objects visible to the operating system, or optionally a filtered list.


There isn’t a cmdlet to get logical disks


For volumes:

PS>  Get-Volume | fl DriveLetter, FileSystemLabel, FileSystem, DriveType, HealthStatus, OperationalSta
tus, SizeRemaining, Size

DriveLetter       : C
FileSystemLabel   : Windows
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 108473528320
Size              : 248480002048


DriveLetter       :
FileSystemLabel   :
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 122884096
Size              : 471855104


DriveLetter       :
FileSystemLabel   : Windows RE tools
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 61980672
Size              : 366997504


DriveLetter       :
FileSystemLabel   : Recovery image
FileSystem        : NTFS
DriveType         : Fixed
HealthStatus      : Healthy
OperationalStatus : OK
SizeRemaining     : 476807168
Size              : 6396309504


As you can see from this quick comparison the same sorts of information is available from the storage cmdlets and WMI. In fact under the hood the storage cmdlets are using WMI – but a set of new classes defined in ROOT/Microsoft/Windows/Storage

WMI Filters

A common mistake with WMI/CIM filters is:

PS>  Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=C:"
Get-WmiObject : Invalid query "select * from Win32_LogicalDisk where DeviceId=C:"
At line:1 char:1
+ Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=C:"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCo


The clue is in the invalid query error message

When you use the –Filter parameter and are testing a property of type string the value you are testing against has to be in quotes

PS>  Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId='C:'"

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 108999528448
Size         : 248480002048
VolumeName   : Windows


The filter is defined as a string so you need to use single quotes inside the double quotes. You could mess around with all single quotes but then you have to escape the inner set of quotes – good luck with that – its an unnecessary exercise in frustration


How do you know the property is a string?

PS>  (Get-CimClass -ClassName Win32_LogicalDisk).CimClassProperties['DeviceId']

Name               : DeviceID
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {CIM_Key, read, key, MappingStrings...}
ReferenceClassName :


The same rules for –Filter apply to Get-CimInstance

Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceId='C:'"