Custom Object with Nested Properties – best way?

Welcome Forums General PowerShell Q&A Custom Object with Nested Properties – best way?

This topic contains 2 replies, has 3 voices, and was last updated by

5 years, 11 months ago.

  • Author
  • #9263

    Topics: 14
    Replies: 42
    Points: 136
    Rank: Participant

    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]@{
            '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??



  • #9267

    Topics: 13
    Replies: 4872
    Points: 1,842
    Helping HandTeam Member
    Rank: Community Hero

    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.

  • #9280

    Topics: 0
    Replies: 132
    Points: 1
    Rank: Member

    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]@{
            '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.

The topic ‘Custom Object with Nested Properties – best way?’ is closed to new replies.