Hardware Reporting with PowerShell

WMI is easy to use and great for querying information about remote machines.  It’s the obvious choice for reporting on hardware usage – especially for scoping EC2 instances.  What is a little more interesting is using the retrieved information to construct a report.

Attached is a PowerShell module that can be used and easily modified to produce XML reports from memory, processor and hard drive information about machines in the environment.  Because a single machine might contain multiple hard drives or processors, xml was a good solution as to how to show all details in a readable report.

Usage

Extract the module to a directory & Import using the Import-Module cmdlet

Invoke-HWCollection has optional parameters for specifying the path & filename for writing to an XML file or specifying a remote computer for querying.  If required, credentials may be specified as well.

The module will return a complex PowerShell object that can be used with scripting.  The example below shows how the returned “Memory Available” property and “Processor Number” properties may be accessed with scripting.

Writing individual details to screen can be achieved using the -Verbose parameter.

Using -XmlOutput will create or append to an xml file all the details harvested from remote machines.  This is useful for batch processing.

The zipped PowerShell Module may be downloaded from here.

A Note on Coding

For the scripters out there, a single PowerShell object can easily contain multiple or nested PowerShell objects.  Combining multiple objects is really straightforward.

The problem I had to deal with was how to reliably write my PowerShell object to XML.  ConvertTo-XML doesn’t work with any complexity in an object.  I decided to use ConvertTo-Json as its reliable and then convert to xml using Dot Net.  The approach works well but you are forced to strip data type attributes from the returned object.

    $jsonoutput = ConvertTo-Json -InputObject $hwresults  
 
    $mStream    = New-Object System.IO.MemoryStream
    $utf8       = [System.Text.Encoding]::UTF8
 
    $bytes      = $utf8.GetBytes($jsonoutput)
    $mStream.Write( $bytes, 0, $bytes.Length )
    $mStream.Position = 0
 
    $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($mStream,[System.Xml.XmlDictionaryReaderQuotas]::Max)
    $xml        = New-Object Xml.XmlDocument
    $xml.Load($jsonReader)
 
    $jsonReader.Close()
    $mStream.Dispose()
 
    #Strip Datatypes from returned xml
 
    $ChildNodes = $Xml.SelectNodes('//*')
    foreach($Child in $ChildNodes){
       [void]$Child.RemoveAllAttributes()
     }