One of my favorite techniques when using WMI in PowerShell is to pipe an object to Select-Object and select all properties. Try this:
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
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.
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. 🙂
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.
There’s really no reason to bother with Traps. Focus on learning how to use Try/Catch.