Easily Filter Empty WMI Properties in PowerShell

Doctor Scripto

Summary: Microsoft Scripting Guy Ed Wilson introduces a WMI filter to remove empty WMI properties by using Windows PowerShell.

 

Microsoft Scripting Guy Ed Wilson here. It is no secret by now that I love Windows Management Instrumentation (WMI). The information I can obtain and the things I can do with it are astounding. In the Windows PowerShell class I was teaching last week in Montreal, I told the class that I think when people say they “do not like WMI,” it is because they are still hampered by nightmares from their experiences of trying to use WMI back in the VBScript days.

Note   This is part four of a multipart article on developing a WMI helper module. On Monday, I created the base WMI module, and included a couple of really great functions that query the WMI schema and return WMI class methods and properties. On Tuesday, I added a function that returns the key property of a WMI class. This is useful when working with WMI instance methods. On Wednesday, I created a function that will return the values of those key properties. Today, I add a HasWMIValue filter to the module.

Another Note   The module for today’s Hey, Scripting Guy! Blog post is on the Scripting Guys Script Repository.

For example, here is a really simple example. I want to obtain information about the BIOS on my computer. Here is the VBScript to do so (copied from the Scripting Guys Script Repository).

VBScript to Get the BIOS information from a local computer

strComputer = “.”

Set objWMIService = GetObject(“winmgmts:” _

    & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”)

 

Set colBIOS = objWMIService.ExecQuery _

    (“Select * from Win32_BIOS”)

 

For each objBIOS in colBIOS

    Wscript.Echo “Build Number: ” & objBIOS.BuildNumber

    Wscript.Echo “Current Language: ” & objBIOS.CurrentLanguage

    Wscript.Echo “Installable Languages: ” & objBIOS.InstallableLanguages

    Wscript.Echo “Manufacturer: ” & objBIOS.Manufacturer

    Wscript.Echo “Name: ” & objBIOS.Name

    Wscript.Echo “Primary BIOS: ” & objBIOS.PrimaryBIOS

    Wscript.Echo “Release Date: ” & objBIOS.ReleaseDate

    Wscript.Echo “Serial Number: ” & objBIOS.SerialNumber

    Wscript.Echo “SMBIOS Version: ” & objBIOS.SMBIOSBIOSVersion

    Wscript.Echo “SMBIOS Major Version: ” & objBIOS.SMBIOSMajorVersion

    Wscript.Echo “SMBIOS Minor Version: ” & objBIOS.SMBIOSMinorVersion

    Wscript.Echo “SMBIOS Present: ” & objBIOS.SMBIOSPresent

    Wscript.Echo “Status: ” & objBIOS.Status

    Wscript.Echo “Version: ” & objBIOS.Version

    For i = 0 to Ubound(objBIOS.BiosCharacteristics)

        Wscript.Echo “BIOS Characteristics: ” & _

            objBIOS.BiosCharacteristics(i)

    Next

Next

 

Windows PowerShell script to retrieve the BIOS information from a local computer

Get-WmiObject win32_bios | format-list *

I am not kidding! It is one short line. In fact, if I use aliases, the command becomes even shorter. Here is the “short” version of the command. The short version is 18 characters long; the VBScript to do exactly the same thing is more than 18 lines long:

gwmi win32_bios | fl *

The output from the Windows PowerShell Get-WMIObject command is shown in the following figure.

Image of output from Get-WMIObject command

With power like this at one’s fingertips, it is hard not to fall in love with WMI and Windows PowerShell. One thing that does annoy me, a bit, is the fact that nearly any query to WMI results in many lines of property names and no values. This was especially distressing in the old VBScript days because it was so much work to retrieve a single property value that I really felt disappointed when the command did not return any information.

To solve the problem of WMI classes that do not populate values in all of the class properties, I have a filter that I use. In fact, when I was writing the scripts for the Windows 7 Inside Out book and the Windows 7 Resource Kit, I used this filter extensively. I decided it is just the sort of thing I want to have constantly available. I use WMI on a daily basis, and therefore piping the output to the filter really makes sense. To make it always available, I modified it a bit and placed it in my WMI module. I uploaded HSGWMIModuleV4 to the Scripting Guys Script Repository. I have comment-based help, but there is no need to go over that. The key portion of the filter is shown here:

$_.properties |

   foreach-object -BEGIN {write-host -ForegroundColor BLUE $_.path} -Process {

     If($_.value -AND $_.name -notmatch “__”)

      {

        @{ $($_.name) = $($_.value) }

      } #end if

    } #end foreach property

 

In the filter, the first thing I do is look at the input object that is piped to the filter, and retrieve a collection of the properties. I pipe the properties to the Foreach-Object cmdlet:

$_.properties |

The first thing I do in the Foreach-Object cmdlet is use the begin parameter to print out the path to WMI instance, as shown here:

foreach-object -BEGIN {write-host -ForegroundColor BLUE $_.path}

In the process portion, I check to see if the property has a value, and if it does not match an underscore. This removes some system properties, and it also removes properties that do not have a value. I create a hash table from the properties and their associated values, and return it. This portion of the code is shown here:

-Process {

     If($_.value -AND $_.name -notmatch “__”)

      {

        @{ $($_.name) = $($_.value) }

      } #end if

To use the HasWMiValue filter, I import my WMI module, and then pipe the results of a Get-WMiObject command to it. This is shown here:

Import-Module HSG*wmi*4

GWMI win32_bios | HasWmiValue

I removed the HSGWMIModuleV4 and did a query of the Win32_bios WMI class while listing all the properties. There are a number of properties from the Win32_Bios class that do not return values. I then import the HSSGWMIModuleV4 and instead of piping the management into Format-List, I pipe it to the HasWMiValue filter. These two commands and their associated output are shown in the following figure.

Image of two commands and associated output

The HasWMIValue filter works great. It lists all of the properties of a WMI class that contain values, and suppresses the system properties as well as the properties that are empty. This output is great for exploring WMI.

Once imported, there is no need to import the WMI module a second time. I can use the HasWmiValue directly in the pipeline. I uploaded the complete WMI helper module to the Scripting Guys Script Repository.

 

Well, that is about all there is to the HasWmiValue filter. I have comment-based help in the function, so if you need additional help, use Get-Help. Until tomorrow, keep on scripting!

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

0 comments

Discussion is closed.

Feedback usabilla icon