Skipping WMI System Properties in PowerShell

One of my favorite techniques when using WMI in PowerShell is to pipe an object to Select-Object and select all properties. Try this:


get-wmiobject win32_bios | select *

It works, but it also gets all of the system properties like __PATH which I rarely care about. I also get other properties like Site and Options which I typically don’t need. So here are some techniques you can use to view all WMI properties that probably matter most. Let’s begin with a typical command:


$os=get-wmiobject Win32_OperatingSystem

This object has a property called Properties which is a collection of WMI PropertyData objects. I could try something like:


PS C:\> $os.properties | select name,value

Name Value
---- -----
BootDevice \Device\HarddiskVolume1
BuildNumber 7601
BuildType Multiprocessor Free
Caption Microsoft Windows 7 Ultimate
CodeSet 1252
CountryCode 1
...

Sure, I can see the properties and values but I don’t really have a good object to work with and this won’t help with multiple instances, at least not without a little extra work.


$d=Get-WmiObject win32_logicaldisk -filter "drivetype=3"
$d | foreach {$_.properties | select name,value }

And maybe that’s all you need. If so, terrific. But I’m looking for an elegant solution. How about expanding the property names and saving them as an array of strings.


[string[]]$prop=$os.properties | Select -expand name
$os | Select -Property $prop

Then I can use them with Select-Object


PS C:\> $os | Select -Property $prop

PS C:\> $os | Select -Property $prop

BootDevice : \Device\HarddiskVolume1
BuildNumber : 7601
BuildType : Multiprocessor Free
Caption : Microsoft Windows 7 Ultimate
CodeSet : 1252
CountryCode : 1
...

That has promise. I could even turn this into a one-line command, assuming I’ve already defined $os.


$os | Select -property ([string[]]($os.properties | Select -expand name))

If I didn’t want to take the extra step, here’s a complex alternative:


Get-WmiObject win32_OperatingSystem | foreach {
Select -InputObject $_ -Property ([string[]](Select -InputObject $_ -expand Properties | Select -expand Name))
}

But this leads to yet another option, using the [WMIClass] type accelerator. When used, PowerShell creates an empty object of the specified WMI class which includes a property list.


PS C:\> [wmiclass]"win32_operatingsystem" | Select -expand Properties | Select name

Name
----
BootDevice
BuildNumber
BuildType
Caption
CodeSet
CountryCode
...

This can be further simplified:


([wmiclass]"win32_operatingsystem").Properties | Select -expand Name

In fact, I can use this in an earlier expression to get the same non-System class results.


get-wmiobject win32_operatingsystem | select -property ([string[]](([wmiclass]"Win32_Operatingsystem").properties | select -expand name))

I’ll admit that’s a lot to type. So I need a shortcut. What about turning this into a scriptblock?


$p={[string[]](([wmiclass]"Win32_Operatingsystem").properties | select -expand name)}

When I invoke the scriptblock, I’ll get the array of property names. I can now use this in my Get-WMIObject expression:


get-wmiobject win32_operatingsystem | select -property (&$p)

Definitely easier to type, but limited. I need the scriptblock to be more flexible so it can accommodate other WMI classes.


$p={Param([string]$class) [string[]](([wmiclass]$class).properties | select -expand name) }

I’ll test it in the shell.


PS C:\> &$p "win32_bios"
BiosCharacteristics
BIOSVersion
BuildNumber
Caption
CodeSet
CurrentLanguage
...

Excellent! Now for the real deal:


PS C:\> get-wmiobject win32_bios | select -property (&$p "win32_bios")

BiosCharacteristics : {4, 7, 8, 9...}
BIOSVersion : {TOSQCI - 6040000, Ver 1.00PARTTBL}
BuildNumber :
Caption : Ver 1.00PARTTBL
CodeSet :
CurrentLanguage :
Description : Ver 1.00PARTTBL
...

That’s exactly what I wanted with minimal effort. All I need is to have that scriptblock loaded in my PowerShell session and remember to specify the class name.


get-wmiobject win32_logicaldisk -filter "drivetype=3" | select -property (&$p "win32_logicaldisk")

Another option would be to turn the scriptblock into a function, but I’ll leave that to you.

Naturally this isn’t perfect. If I need to query a remote computer with classes that aren’t on my computer, this won’t work; at least not without some revisions. But since I’d say 90% or more of WMI commands in PowerShell are with the Win32 classes, I think this is a handy trick to stick in your PowerShell toolbox.

If you’d like to try some of my code samples, you can download demo-wmiproperties.

4 thoughts on “Skipping WMI System Properties in PowerShell

  1. We can also make use of the -ExcludeProperty parameter of the Select-Object cmdlet to filter out properties that starts with double underscore (system properties):

    Get-WmiObject Win32_OperatingSystem | Select-Object -Property * -ExcludeProperty __*

    • Yes and no. That will get rid of System properties, but you still get Site, Qualifiers and a few more. I’d have to use an expression like this:

      PS C:\> gwmi win32_bios | Select * -exclude “__*”,Scope,Path,Options,Classpath,Systemproperties,Qualifiers,site,container,Properties

      Which is no where near as sexy. 🙂

  2. Traps.. more help on traps would be fantastic. I’m still hianvg issues figuring out how to hunt down what I can trap for what error message. I’ve read your page about 100times now and still am missing things.

Comments are closed.