Monthly Archive



Win32_ReliabilityRecords Class

The Win32_ReliabilityRecords class was introduced with Windows 7. It contains information from the Windows Event Log related to system reliability.


The most interesting properties are the Message and the TimeGenerated

£> Get-WmiObject -class win32_reliabilityRecords | select -First 1 | fl Message, TimeGenerated

Message       : Installation Successful: Windows successfully installed the following update: Definition Update for  Windows Defender - KB2267602 (Definition 1.207.1367.0)
TimeGenerated : 20150929170914.620000-000


Notice the usual delightful date format on TimeGenerated


Easiest way to resolve this and get sensibly formatted date is to use the CIM cmdlets

£> Get-CimInstance -ClassName win32_reliabilityRecords | select -First 1 | fl Message, TimeGenerated

Message       : Installation Successful: Windows successfully installed the following update: Definition Update for  Windows Defender - KB2267602 (Definition 1.207.1367.0)
TimeGenerated : 29/09/2015 18:09:14


Now you have a date you can read easily.

WMI dates

Dates as reported by WMI still seem to cause a lot of problems. If you use the WMI cmdlets

£> Get-WmiObject -Class Win32_OperatingSystem | select *date* | fl

InstallDate   : 20131205101649.000000+000
LocalDateTime : 20150728121320.002000+060


That format is year, month, day, hour, minute, second then fractions of a second after the decimal point with the final +nnn indicating an offset from Greenwich Mean Time  (UTC) for time zones and daylight saving time.


You can read the date presented by WMI but its not intuitive.


The PowerShell team added a ConvertToDateTime() to the object output by WMI so that you can easily perform date conversions

£> Get-WmiObject -Class Win32_OperatingSystem | select @{N='Install'; E={$_.ConvertToDateTime($_.Installdate)}}, @{N='Lo
calDate'; E={$_.ConvertToDateTime($_.LocalDateTime)}} | fl

Install   : 05/12/2013 10:16:49
LocalDate : 28/07/2015 12:16:26


Though my preferred solution these days is to use the CIM cmdlets as they convert the date for you without any extra effort

£> Get-CimInstance -ClassName Win32_OperatingSystem | select *date* | fl

InstallDate   : 05/12/2013 10:16:49
LocalDateTime : 28/07/2015 12:17:29

CIM filters

I was looking up Win32_SystemDriver on the MSDN site and noticed there was some PowerShell example code


Get-WmiObject -Class Win32_SystemDriver |
Where-Object -FilterScript {$_.State -eq "Running"} |
Where-Object -FilterScript {$_.StartMode -eq "Manual"} |
Format-Table -Property Name,DisplayName


A better way to write this would be:

Get-WmiObject -Class Win32_SystemDriver -Filter "State='Running' AND StartMode='Manual'" | Format-Table -Property Name, DisplayName –AutoSize




Get-CimInstance -ClassName Win32_SystemDriver -Filter "State='Running' AND StartMode='Manual'" | Format-Table -Property Name, DisplayName -AutoSize


Do the filtering in the CIM call – especially if you’re running this against a number of remote machines. That way you limit the network traffic you’re returning

WMF 5.0 April 2015 preview – – software inventory logging

A software inventory module is now included with the April 2015 WMF 5.0 preview

£> Get-Command -Module SoftwareInventoryLogging | select Name



Windows updates are always a good place to start poking into your systems

£> Get-Command Get-SilWindowsUpdate -Syntax

Get-SilWindowsUpdate [[-ID] <string[]>] [-CimSession <CimSession[]>]
[-ThrottleLimit <int>] [-AsJob] [<CommonParameters>]

£> Get-SilWindowsUpdate

ID          : KB3055381
InstallDate : 4/30/2015



The parameters for Get-SilWindowsUpdate look like those I’d expect from a CDXML module. Inspection of C:\Windows\System32\WindowsPowerShell\v1.0\modules\SoftwareInventoryLogging\

shows  a number of cdxml files



The WMF 5,0 release notes supply a link to further data of software inventory logging – interestingly its flagged as a Windows Server 2012 R2 page.

Trying the cmdlet against a Windows Server 2012 R2 system running WMF 4.0 (with the November 2014 roll up)

$cs = New-CimSession -ComputerName W12R2SUS
Get-SilWindowsUpdate -CimSession $cs

£> Get-SilWindowsUpdate -CimSession $cs

ID             : KB3006193
InstallDate    : 1/5/2015
PSComputerName : W12R2SUS



This means the class is on our Windows Server 2012 R2 box so we could use it directly

£> Get-CimInstance -Namespace root/InventoryLogging -ClassName  MsftSil_WindowsUpdate | Format-Table -a

ID                  InstallDate                                PSComputerName
--                   -----------                                 --------------
KB3006193 1/5/2015 12:00:00 AM
KB2894856 9/14/2014 12:00:00 AM



This module supplies a useful way to find out the software installed on our systems – I’ll be digging into this over a few more posts

Blocksize missing?

I recently had a question asking why the Bloacksize property on Win32_LogicalDisk is empty but is populated on Win32_Volume.

The thing is to remember the underlying thing that these 2 CIM classes represent.


A logical disk is a subdivision of an extended partition. An extended partition can hold one or more logical disks.


When you create a volume on a disk you use either a primary partition or a logical disk from an extended partition. Until you format the volume you can’t have a block size as that is determined by the parameters you use to perform the format.


The documentation for Win32_LogicalDisk states that block size is not populated for logical disks

OMI/CIM/WMI dictionary

Don Jones provides a very good summary of the similarities and differences between WMI, CIM and OMI

Recommended reading if you’re using these technologies

Query vs Filter

I’ve tended to advocate using the –Filter parameter rather than the –Query parameter with the CIM (and WMI) cmdlets but a recent post on the Windows Management Infrastructure blog has me questioning that decision.


Using Measure-Command I tried various pairs of commands – such as:


Measure-Command {Get-CimInstance -ClassName Win32_Directory -Filter "Name = 'C:\\Test2'"}


Measure-Command {Get-CimInstance -Query "SELECT * FROM Win32_Directory WHERE Name = 'C:\\Test2'"}


The results weren’t conclusive but it seems that at worst there is no significant difference between the approaches and at best using a query is significantly faster. 


At the moment my best advice would be use the –Filter parameter if you want to reduce typing but try –Query if speed becomes your main issue.

Copy a file with WMI

A question came up on the forum about copying files with CIM (WMI). I normally use Copy-Item rather than CIM as its easier. The questioner was using CIM_LogicalFile when I’ve normally used CIM_DataFile so I decided to take a look at the class. In reality the two classes are very similar and CIM-datafile could be substituted for CIM_LogicalFile in the code that follows.


The obvious starting point is to use the Copy method on the CIM_LogicalFile class


$files = Get-WmiObject -Class CIM_LogicalFile -Filter "Path = '\\Test\\' AND Extension = 'txt'"

foreach ($file in $files) {
$newfile = "C:\Test2\$($file.FileName).$($file.Extension)"



Couple of points to note. In the Path part of the filter you have to escape the \ delimiter.  Extension doesn’t include the ‘.’

You have to give the full path – including file name - to the loaction to which you want to copy the file. In this case you don’t have to escape the \ delimiter. Consistency is a wonderful thing and usually absent from WMI.


You can also use Invoke-WmiMethod


$files = Get-WmiObject -Class CIM_LogicalFile -Filter "Path = '\\Test\\' AND Extension = 'txt'"

foreach ($file in $files) {
$newfile = "C:\Test2\$($file.FileName).$($file.Extension)"
Invoke-WmiMethod -InputObject $file  -Name Copy -ArgumentList $newfile




use the new CIM cmdlets


$files = Get-CimInstance -ClassName CIM_LogicalFile -Filter "Path = '\\Test\\' AND Extension = 'txt'"

foreach ($file in $files) {
$newfile = "C:\Test2\$($file.FileName).$($file.Extension)"
Invoke-CimMethod -InputObject $file  -MethodName Copy -Arguments @{Filename = $newfile}



In this case you have to give the argument name for the method as well as its value. You can discover the method parameters using Get-CimClass


$class = Get-CimClass CIM_LogicalFile

£> $class.CimClassMethods["Copy"].Parameters

Scripting Guy CDXML series finished

My CDXML series on the Scripting Guy blog finished today.  The 4 articles are:

Scripting Guy CDXML series

Today starts a four part series I’ve written for the Scripting Guy blog on using CDXML to create a module to work with the registry.  Don’t know what CDXML is – you will when you’ve read the series


The first post is at