Powershell – Sorting Custom Object Columns

powershell

Lately, I've been playing around with custom objects in PowerShell. I'm getting the hang of it except I don't understand why PowerShell displays my objects in a seemingly random order. For example

$i = 0; $a = @()
$Disks = Get-WMIObject -Class Win32_LogicalDisk

ForEach($Disk in $Disks){

    $props = @{'Disk' = $Disks.DeviceID[$i];
    'Size GB' = "{0:F1}" -f ($Disks.size[$i] / 1GB)}
    $a += New-Object psobject -Property $props
    $i++

}

$a

Output is shown as 'Size GB' then 'Disk'. I want 'Disk' then 'Size GB'. Example 2:

$Computers = 'Server1', 'Server2', 'Server3'
$ComputerInfo = 1..$Computers.Length
$props = @{NAME = ""; MAC_ADDR = ""; IP_ADDR = "" }
$Cred = Get-Credential -Message "Enter Credentials"
$i=0

#Gather requested information for each $computer in $computers
ForEach ($Computer in $Computers) {

    Write-Host "Gathering information on $computer..."
    $ComputerInfo[$i] = New-Object psobject -property $props

    Try {
        $wmiquery = get-wmiobject win32_networkadapterconfiguration -computer $Computer -filter "IPEnabled='True'" -Credential $Cred -ErrorAction SilentlyContinue
        $ComputerInfo[$i].NAME = $computer
        $ComputerInfo[$i].MAC_ADDR = $wmiquery.MACAddress
         $ComputerInfo[$i].IP_ADDR = $wmiquery.IPAddress[0]
    } Catch {
         Write-Host "Unable to query: $computer"
    }

    $i++
}

#Display information
$ComputerInfo

Output is shown as 'MAC_ADDR' then 'IP_ADDR' then 'NAME'. I want 'NAME' then 'MAC_ADDR' then 'IP_ADDR'.

Best Answer

The method of creating custom objects that you are making use of in the above script do not have a method to sort them. To have the results returned in a predefined order you have to change the way the custom object is made.

$Disks = Get-WMIObject -Class Win32_LogicalDisk

$arr = @()
$Disks | ForEach-Object{
    $obj = New-Object -TypeName PSObject
    $obj | Add-Member -MemberType NoteProperty -Name Disk -Value $_.DeviceID
    $obj | Add-Member -MemberType NoteProperty -Name "Size GB" -Value $([math]::truncate($_.Size / 1GB))
    $arr += $obj
}

Write-Output $arr

The above will always return the object properties in the order they are added, in this case Disk then Size GB.

More on working with custom object can be found here.