{"id":12271,"date":"2011-10-27T00:01:00","date_gmt":"2011-10-27T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/10\/27\/easily-filter-empty-wmi-properties-in-powershell\/"},"modified":"2011-10-27T00:01:00","modified_gmt":"2011-10-27T00:01:00","slug":"easily-filter-empty-wmi-properties-in-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/easily-filter-empty-wmi-properties-in-powershell\/","title":{"rendered":"Easily Filter Empty WMI Properties in PowerShell"},"content":{"rendered":"<p><strong>Summary:<\/strong> Microsoft Scripting Guy Ed Wilson introduces a WMI filter to remove empty WMI properties by using Windows PowerShell.<\/p>\n<p>&nbsp;<\/p>\n<p>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 &ldquo;do not like WMI,&rdquo; it is because they are still hampered by nightmares from their experiences of trying to use WMI back in the VBScript days.<\/p>\n<p style=\"padding-left: 30px\"><b>Note<\/b>&nbsp; &nbsp;This is part four of a multipart article on developing a WMI helper module. On <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/24\/a-powershell-wmi-helper-module-described.aspx\">Monday<\/a>, 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 <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/25\/use-powershell-to-easily-find-the-key-property-of-a-wmi-class.aspx\">Tuesday<\/a>, I added a function that returns the key property of a WMI class. This is useful when working with WMI instance methods. On <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/10\/26\/use-a-powershell-function-to-get-wmi-key-property-values.aspx\">Wednesday<\/a>, I created a function that will return the values of those key properties. Today, I add a HasWMIValue filter to the module.<\/p>\n<p style=\"padding-left: 30px\"><strong>Another Note&nbsp;&nbsp;<\/strong> The module for today&rsquo;s Hey, Scripting Guy! Blog post is on the <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/Scripting-Guys-WMI-Helper-5a03aaeb\">Scripting Guys Script Repository<\/a>.<\/p>\n<p>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 <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/ac1a95ef-96db-4706-845a-89e818a4a04f\">Scripting Guys Script Repository<\/a>).<\/p>\n<p><b>VBScript to Get the BIOS information from a local computer<\/b><\/p>\n<p style=\"padding-left: 30px\">strComputer = &#8220;.&#8221;<\/p>\n<p style=\"padding-left: 30px\">Set objWMIService = GetObject(&#8220;winmgmts:&#8221; _<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; &amp; &#8220;{impersonationLevel=impersonate}!\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Set colBIOS = objWMIService.ExecQuery _<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; (&#8220;Select * from Win32_BIOS&#8221;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">For each objBIOS in colBIOS<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Build Number: &#8221; &amp; objBIOS.BuildNumber<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Current Language: &#8221; &amp; objBIOS.CurrentLanguage<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Installable Languages: &#8221; &amp; objBIOS.InstallableLanguages<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Manufacturer: &#8221; &amp; objBIOS.Manufacturer<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Name: &#8221; &amp; objBIOS.Name<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Primary BIOS: &#8221; &amp; objBIOS.PrimaryBIOS<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Release Date: &#8221; &amp; objBIOS.ReleaseDate<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Serial Number: &#8221; &amp; objBIOS.SerialNumber<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;SMBIOS Version: &#8221; &amp; objBIOS.SMBIOSBIOSVersion<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;SMBIOS Major Version: &#8221; &amp; objBIOS.SMBIOSMajorVersion<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;SMBIOS Minor Version: &#8221; &amp; objBIOS.SMBIOSMinorVersion<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;SMBIOS Present: &#8221; &amp; objBIOS.SMBIOSPresent<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Status: &#8221; &amp; objBIOS.Status<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;Version: &#8221; &amp; objBIOS.Version<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; For i = 0 to Ubound(objBIOS.BiosCharacteristics)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Wscript.Echo &#8220;BIOS Characteristics: &#8221; &amp; _<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objBIOS.BiosCharacteristics(i)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Next<\/p>\n<p style=\"padding-left: 30px\">Next<\/p>\n<p>&nbsp;<\/p>\n<p><b>Windows PowerShell script to retrieve the BIOS information from a local computer <\/b><\/p>\n<p style=\"padding-left: 30px\">Get-WmiObject win32_bios | format-list *<\/p>\n<p>I am not kidding! It is one short line. In fact, if I use aliases, the command becomes even shorter. Here is the &ldquo;short&rdquo; 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:<\/p>\n<p style=\"padding-left: 30px\">gwmi win32_bios | fl *<\/p>\n<p>The output from the Windows PowerShell <b>Get-WMIObject<\/b> command is shown in the following figure.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6215.hsg-10-27-11-1.png\"><img decoding=\"async\" title=\"Image of output from Get-WMIObject command\" alt=\"Image of output from Get-WMIObject command\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6215.hsg-10-27-11-1.png\" \/><\/a><\/p>\n<p>With power like this at one&rsquo;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.<\/p>\n<p>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 <i>Windows 7 Inside Out<\/i> 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 <b>HSGWMIModuleV4<\/b> 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:<\/p>\n<p style=\"padding-left: 30px\">$_.properties |<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp; foreach-object -BEGIN {write-host -ForegroundColor BLUE $_.path} -Process {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; If($_.value -AND $_.name -notmatch &#8220;__&#8221;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @{ $($_.name) = $($_.value) }<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } #end if<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; } #end foreach property<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p>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 <b>Foreach-Object<\/b> cmdlet:<\/p>\n<p style=\"padding-left: 30px\">$_.properties |<\/p>\n<p>The first thing I do in the <b>Foreach-Object<\/b> cmdlet is use the <i>begin<\/i> parameter to print out the path to WMI instance, as shown here:<\/p>\n<p style=\"padding-left: 30px\">foreach-object -BEGIN {write-host -ForegroundColor BLUE $_.path}<\/p>\n<p>In the <b>process<\/b><i> <\/i>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:<\/p>\n<p style=\"padding-left: 30px\">-Process {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp; If($_.value -AND $_.name -notmatch &#8220;__&#8221;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @{ $($_.name) = $($_.value) }<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } #end if<\/p>\n<p>To use the <b>HasWMiValue<\/b> filter, I import my WMI module, and then pipe the results of a <b>Get-WMiObject<\/b> command to it. This is shown here:<\/p>\n<p style=\"padding-left: 30px\">Import-Module HSG*wmi*4<\/p>\n<p style=\"padding-left: 30px\">GWMI win32_bios | HasWmiValue<\/p>\n<p>I removed the <b>HSGWMIModuleV4<\/b> and did a query of the <b>Win32_bios<\/b> WMI class while listing all the properties. There are a number of properties from the <b>Win32_Bios<\/b> class that do not return values. I then import the <b>HSSGWMIModuleV4<\/b> and instead of piping the management into <b>Format-List<\/b>, I pipe it to the <b>HasWMiValue<\/b> filter. These two commands and their associated output are shown in the following figure.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6175.HSG-10-27-11-2.png\"><img decoding=\"async\" title=\"Image of two commands and associated output\" alt=\"Image of two commands and associated output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6175.HSG-10-27-11-2.png\" \/><\/a><\/p>\n<p>The <b>HasWMIValue<\/b> 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.<\/p>\n<p>Once imported, there is no need to import the WMI module a second time. I can use the <b>HasWmiValue<\/b> directly in the pipeline. I uploaded the complete WMI helper module to the <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/Scripting-Guys-WMI-Helper-5a03aaeb\">Scripting Guys Script Repository<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>Well, that is about all there is to the <b>HasWmiValue<\/b> filter. I have comment-based help in the function, so if you need additional help, use <b>Get-Help<\/b>. Until tomorrow, keep on scripting!<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy Ed Wilson introduces a WMI filter to remove empty WMI properties by using Windows PowerShell. &nbsp; 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 [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[3,4,45,6],"class_list":["post-12271","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell","tag-wmi"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy Ed Wilson introduces a WMI filter to remove empty WMI properties by using Windows PowerShell. &nbsp; 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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12271","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=12271"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12271\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=12271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=12271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=12271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}