Author Posts

August 9, 2013 at 6:08 am

So I am writing an eventual function to connect to one or many of our servers and retrieve various information using WMI:

– Computer Name, Manufacturer, Model, Service Tag (serial number), OS, Architecture, # Of Processors, RAM, Disk).

I have this working so far, I am just wondering if there is a better way to do it. Currently, this is how I am grabbing the disk –

Get-WmiObject -Class Win32_LogicalDisk -ComputerName $ComputerName -Credential $Credential -Filter "DriveType=3" | 
        Select DeviceID, @{n='Disk Size (GB)';e={$_.size / 1gb -as [int]}}, @{n='FreeSpace (GB)';e={$_.freespace / 1gb -as [int]}} -OutVariable diskInfo

Once I grab all of the different things I want, I create an ordered hash table:

$infoHash = [ordered]@{
        'ComputerName'=$ComputerName
        'Manufacturer'= $sys.manufacturer
        'Model'= $sys.model 
        'ServiceTag' = $serviceTag
        'OperatingSystem' = $os.caption
        'Architecture' = $os.OSArchitecture
        'Processors'= $sys.NumberOfProcessors
        'Memory'= $sys.TotalPhysicalMemory / 1gb -as [int]
        'Disk' = $diskinfo 
    }

$computerInfo = New-Object -TypeName PSObject -Property $infohash

When I take my custom object and pipe it to format-table, everything looks good – except for the diskInfo. I would love it if it had like a table in a table so that I could see it when I run this.

Is there a way to either set this up properly with the objects or output it to the screen??

Thanks

sb

August 9, 2013 at 6:33 am

You're constructing the object properly, but PowerShell's built-in formatting system can't handle object hierarchies in a "table in a table." If you pipe your output to Format-Custom, you'll see that it SEES the hierarchy, but Format-Table just can't do anything with it (nor could Format-List). Your only native solution would be to create your own custom format in a .format.ps1xml file, designed to handle the output of your command specifically. That's a pretty advanced topic, as I don't think the custom formats are actually documented in any real detail anyplace.

August 9, 2013 at 8:41 am

You can get pretty close to what you are after without mucking around with any .format.ps1xml file stuff. Here's a script I put together to do this, and the output format is almost perfect for what you are looking for:

$PSDefaultParameterValues = @{
    'Get-WmiObject:ComputerName' = 'localhost'
    'Get-WmiObject:Credential' = [System.Management.Automation.PSCredential]::Empty
}

$serviceTag = 'P0w3r$h3llR0ck$!'
$os = Get-WmiObject -Class Win32_OperatingSystem
$sys = Get-WmiObject -Class Win32_ComputerSystem
$ld = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3"
$diskInfoCollection = @()
foreach ($item in $ld) {
    $diskInfo = [pscustomobject]@{
                DeviceId = $item.DeviceID
        'Disk Size (GB)' = ($item.size / 1gb) -as [int]
        'FreeSpace (GB)' = ($item.freespace / 1gb) -as [int]
    }
    Add-Member -Force -InputObject $diskInfo -MemberType ScriptMethod -Name ToString -Value {
        [System.Environment]::NewLine + (($this | Format-List * | Out-String) -replace '^\s+|\s+$')
    }
    $diskInfoCollection += Add-Member -InputObject $diskInfo -TypeName My.DiskInfo -PassThru
}
$computerInfo = [pscustomobject]@{
        'ComputerName'=$ComputerName
        'Manufacturer'= $sys.manufacturer
        'Model'= $sys.model 
        'ServiceTag' = $serviceTag
        'OperatingSystem' = $os.caption
        'Architecture' = $os.OSArchitecture
        'Processors'= $sys.NumberOfProcessors
        'Memory'= $sys.TotalPhysicalMemory / 1gb -as [int]
        'Disk' = $diskInfoCollection
    }
Add-Member -InputObject $computerInfo -TypeName My.ComputerInfo

$computerInfo | Format-List *

The magic is in the ToString method definition for the custom My.DiskInfo objects. That controls how those objects are resolved to string when you view the contents of the containing collection in your list of parent objects.

You could also create a "display" property that shows the diskinfo as a nested table (maybe call it DiskTable), and have it contain the nested table as a string for easy reading.