Get-wmiobject wrapper
From Svendsen Tech Powershell Wiki
Contents |
General Information
Get-WmiObject-Wrapper.ps1, available for download below, is a "wrapper" around Get-WmiObject. It is designed to retrieve and collect data from a list of computers, and I built in support for a WMI timeout parameter, which is missing from Get-WmiObject. However, during testing it appears that the timeout is not in effect on certain computers that "get stuck", which is really the problem I set out to solve with the timeout parameter. See the aforementioned article for further details.
I decided to store the retrieved data using XML since PowerShell v2 has decent support for it.
It took a lot of experimentation to get this right and I had to make a few compromises in the code to get it working. You can look at the source code by clicking the text file download links in the downloads section below.
How It Works
You specify a list of computers (use "(gc computers.txt)" to use computer names from a file) and the WMI class or classes and the property or properties you want to retrieve from each class, from these computers. This will be stored in an XML structure that supports this type of data. I demonstrate how to parse the XML with a ready-made script in the examples below.
You specify WMI classes and the properties you want from each class with a special string in this format:
"wmi_class1:prop1,prop2|wmi_class2:prop1|wmi_class3:prop1,prop2,prop3"
Rules:
- First you specify the class, followed by a colon, then a property or properties separated by commas.
- Multiple class/property groups are separated by pipes.
In the example below, the string in this format that I use is "win32_operatingsystem:version|win32_computersystem:totalphysicalmemory,model"
The resulting XML looks like this, and you can now use the report generator to extract data and produce CSV reports:
Parameters
- -ComputerName: Required. Array of strings with computer names. Use "(gc .\computers.txt)" to use a file.
- -OutputFile: Required. Output file. You will be prompted to overwrite it unless you specify -Clobber. The XML save method requires a full path, so I do some tests to see if a full path was specified and if it looks like a relative path, you will be asked if you want to use the current working directory.
- -MultiClassProperty: Required. You specify WMI classes and the properties you want from each class with a special string in this format: "wmi_class1:prop1,prop2|wmi_class2:prop1|wmi_class3:prop1,prop2,prop3".
- -Timeout: Optional. A time span object. The default is "0:0:10", which is 10 seconds.
- -NoPingTest: Optional. Specify this if you do NOT want to skip computers that do not respond to ICMP echo (ping).
- -Clobber: Optional. Overwrite the specified output file without prompting if it already exists.
- -Scope: Optional. The WMI management scope. Usually not necessary. By default "\\${Computer}\root\cimv2" will be used, while this lets you replace the part "root\cimv2" with what you specify instead.
Access The Data In The XML From The Command Line
I figure if anyone's going to use this, you need a convenient way of retrieving data from the XML. Of course, you could write your own parser and extract what you need, but that might be quite a bit of work, especially if you haven't done it before and need to learn how. So I wrote a simple, but, I dare say, highly flexible, report generator for you.
With Gwmi-Wrapper-Report.ps1 you can dump the entire XML to "CSV strings" (the default delimiter is " | ") in the format "computer name | class name | property name | property value". This is useful for visual inspection or making reports in some desired format.
Let me repeat this clearly: You can produce CSV reports from the XML data easily. Just use the -Headers and -CsvDelimiter parameters and redirect to a file with Out-File (if the output lines don't exceed the console window width), Add-Content or Set-Content. To process data properly with Import-Csv you need a single-character delimiter. If there are no commas in the data - you can use -CsvDelimiter ',' - and have the default behaviour with Import-Csv. Also see the example about exporting to CSV. It's easy!
You might want to read more about text processing with regular expressions here.
Gwmi-Wrapper-Report Parameters
The parameters are:
- -XmlFile: Required. The XML file to parse.
- -ComputerName: Optional. Default "all". Specify computer or computers to filter on. Only computer names matching those you specify here will be displayed.
- -Class: Optional. Default "all". Specify WMI class or classes to filter on. Only classes matching those names you specify here will be displayed.
- -Property: Optional. Default "all". Specify property or properties to filter on. Only properties matching those names you specify here will be displayed.
- -CsvDelimiter: Optional. Specify a custom CSV delimiter string. Use a single-char value, such as "," or ";" if you redirect to a file and later want to use Import-Csv on it.
- -Headers: Optional. Print the headers "Computer, Class, Property, Value". For use when using -CsvDelimiter and redirecting to a CSV file for later use with Import-Csv.
Example Use
These reports are based on the XML from the above screenshot (notice the command).
Dumping All Data
To dump everything, you can use the command:
> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml
And in my case I get this output:
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml 2008r2esxi | win32_computersystem | model | VMware Virtual Platform 2008r2esxi | win32_computersystem | totalphysicalmemory | 2147016704 2008r2esxi | win32_operatingsystem | version | 6.1.7601 server2008 | win32_computersystem | model | VMware Virtual Platform server2008 | win32_computersystem | totalphysicalmemory | 2146136064 server2008 | win32_operatingsystem | version | 6.0.6002 silverstone | win32_computersystem | Error | Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" silverstone | win32_operatingsystem | Error | Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" ubuntu64esxi | win32_computersystem | Error | Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" ubuntu64esxi | win32_operatingsystem | Error | Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" win7esxi | win32_computersystem | model | VMware Virtual Platform win7esxi | win32_computersystem | totalphysicalmemory | 2147016704 win7esxi | win32_operatingsystem | version | 6.1.7601 winxpesxi | win32_computersystem | model | VMware Virtual Platform winxpesxi | win32_computersystem | totalphysicalmemory | 536330240 winxpesxi | win32_operatingsystem | version | 5.1.2600
You can of course process this with Select-String, but I built in some filtering options which I will now demonstrate.
Dumping Data With A Different CSV Delimiter
Use the -Headers and -CsvDelimiter parameters if you want to redirect to a file.
# Dump all hardware models. PS C:\PS> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property model -CsvDelimiter ',' 2008r2esxi,win32_computersystem,model,VMware Virtual Platform server2008,win32_computersystem,model,VMware Virtual Platform win7esxi,win32_computersystem,model,VMware Virtual Platform winxpesxi,win32_computersystem,model,VMware Virtual Platform # Redirect to a file. Don't forget "-Headers"! PS C:\PS> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property model -CsvDelimiter ',' -Headers | Set-Content model.csv # Process it with Import-Csv. PS C:\PS> Import-Csv .\model.csv | ft -auto Computer Class Property Value -------- ----- -------- ----- 2008r2esxi win32_computersystem model VMware Virtual Platform server2008 win32_computersystem model VMware Virtual Platform win7esxi win32_computersystem model VMware Virtual Platform winxpesxi win32_computersystem model VMware Virtual Platform
Filtering On A Computer Name
Let's filter on the computer name "server2008":
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -ComputerName server2008 server2008 | win32_computersystem | model | VMware Virtual Platform server2008 | win32_computersystem | totalphysicalmemory | 2146136064 server2008 | win32_operatingsystem | version | 6.0.6002
Filtering On A Property
Why not retrieve only the model for all computers:
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property model 2008r2esxi | win32_computersystem | model | VMware Virtual Platform server2008 | win32_computersystem | model | VMware Virtual Platform win7esxi | win32_computersystem | model | VMware Virtual Platform winxpesxi | win32_computersystem | model | VMware Virtual Platform
A side-effect here is that the computers with errors and no ping reply are filtered out, because the properties are named "Error" and "NoPing". There's only one Error or NoPing entry per class. To list errors, use:
> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property error
To list computers that did not respond to ping, use:
> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property NoPing
Filtering On A Class
Or just get the Win32_Operatingsystem class stuff (in this case the property "version"):
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Class Win32_OperatingSystem 2008r2esxi | win32_operatingsystem | version | 6.1.7601 server2008 | win32_operatingsystem | version | 6.0.6002 silverstone | win32_operatingsystem | Error | Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" ubuntu64esxi | win32_operatingsystem | Error | Exception calling "Get" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" win7esxi | win32_operatingsystem | version | 6.1.7601 winxpesxi | win32_operatingsystem | version | 5.1.2600
Notice how you get the errors as well. We can pull out the trick from example three with -Property version. In which case the class specification is useless since the property name doesn't exist in any other class, but that's specific to the example data.
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Class Win32_OperatingSystem -Property version 2008r2esxi | win32_operatingsystem | version | 6.1.7601 server2008 | win32_operatingsystem | version | 6.0.6002 win7esxi | win32_operatingsystem | version | 6.1.7601 winxpesxi | win32_operatingsystem | version | 5.1.2600
You could also have used Select-String like this (you need to escape the pipes which have a special meaning in regular expressions):
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Class Win32_OperatingSystem | Select-String -NotMatch '\| Error \|' 2008r2esxi | win32_operatingsystem | version | 6.1.7601 server2008 | win32_operatingsystem | version | 6.0.6002 win7esxi | win32_operatingsystem | version | 6.1.7601 winxpesxi | win32_operatingsystem | version | 5.1.2600
Technically, if you wanted to be painfully precise, you would have to use a regular expression like "^(?:[^|]+(?: \| )?){2}Error \|" or maybe "^(?:[^|]+\|){2} Error \|".
Combined Filtering
You can also specify multiple parameters and they'll filter accordingly (they will basically be inclusively combined):
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Class win32_computersystem,win32_operatingsystem -Property model,version -ComputerName server2008,winxpesxi server2008 | win32_computersystem | model | VMware Virtual Platform server2008 | win32_operatingsystem | version | 6.0.6002 winxpesxi | win32_computersystem | model | VMware Virtual Platform winxpesxi | win32_operatingsystem | version | 5.1.2600
Practical Example
To generate a simple report of memory in MB for all computers, you can use something like this one-liner:
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property TotalPhysicalMemory |
%{ $Computer, $Mem = ($_ -split ' \| ')[0,3]; $Computer + ': ' + ($Mem/1MB).ToString('N') }
2008r2esxi: 2,047.55
server2008: 2,046.71
win7esxi: 2,047.55
winxpesxi: 511.48
Another Practical Example
For some reason you might want to find out how much memory computers running Windows 7 or Windows 2008 R2 have. This can be done in a two-step process with Gwmi-Wrapper-Report. First get the computers that have Windows 6.1:
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml
-Property version -Class Win32_OperatingSystem |
Where { ($_ -split ' \| ')[3] -match '^6\.1\.' }
2008r2esxi | win32_operatingsystem | version | 6.1.7601
win7esxi | win32_operatingsystem | version | 6.1.7601
Then get only the computer names and save them to a file:
# Verify output
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Property version
-Class Win32_OperatingSystem |
Where { ($_ -split ' \| ')[3] -match '^6\.1\.' } | %{ ($_ -split ' \| ')[0] }
2008r2esxi
win7esxi
# Then save the computer names to a file (win61.txt)
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml
-Property version -Class Win32_OperatingSystem |
Where { ($_ -split ' \| ')[3] -match '^6\.1\.' } |
%{ ($_ -split ' \| ')[0] } | Out-File win61.txt
Then you can feed this file to the -ComputerName parameter and otherwise use the same command as in example six:
PS C:\prog\Powershell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml
-Property TotalPhysicalMemory -ComputerName (gc .\win61.txt) |
%{ $Computer, $Mem = ($_ -split ' \| ')[0,3]; $Computer + ': ' + ($Mem/1MB).ToString('N') }
2008r2esxi: 2,047.55
win7esxi: 2,047.55
Exporting to a CSV File
Now this is useful. Let's demonstrate how to export to a CSV file. I use the -Headers parameter for adding default headers so I don't have to make some up and add them with the -Header parameter for the Import-Csv cmdlet afterwards. I also set a single-char CSV delimiter with -CsvDelimiter ';'. This is then redirected to a file with " > report.csv". If there are no commas in the data, you can of course use the default delimiter (a comma).
PS C:\> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Headers -ComputerName server2008 -CsvDelimiter ';' > report.csv PS C:\> Import-Csv .\report.csv -Delimiter ';' Computer Class Property Value -------- ----- -------- ----- server2008 win32_bios manufacturer Phoenix Technologies LTD server2008 win32_computersystem model VMware Virtual Platform server2008 win32_computersystem totalphysicalmemory 2146136064 server2008 win32_operatingsystem version 6.0.6002
To make a CSV report with just the models for all computers, you can use something like this:
PS C:\> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\wmi.xml -Headers
-Property Model -CsvDelimiter ',' | Set-Content model.csv
PS C:\prog\Powershell> Import-Csv .\model.csv |
Select Computer, @{n='Hardware Model';e={$_.Value}} | # you can also just use "Select Computer,Value"...
Format-Table -AutoSize
Computer Hardware Model
-------- --------------
2008r2esxi VMware Virtual Platform
server2008 VMware Virtual Platform
win7esxi VMware Virtual Platform
winxpesxi VMware Virtual Platform
Downloads
- Get-WmiObject-Wrapper.ps1.txt (right-click and "save as")
- Gwmi-Wrapper-Report.ps1.txt (right-click and "save as")

