Reputation: 545
How can I change the column ordering of the output my code produces:
$apps = Import-CSV apps.csv
$computers = Import-CSV compobj.csv
foreach ($computer in $computers) {
$computerLob = $computer.lob
$lobApps = $apps | ? {$_.lob -eq $computerLob }
foreach ($app in $lobApps) {
$computerHostname = $computer.hostname
$appLocation = $app.location
$installed=Test-Path "\\$computerHostname\$appLocation"
New-Object PSObject -Property @{
Computer=$computer.hostname
App=$app.appname
Installed=$installed
}
}
Currently it's producing the columns in the following order: Installed,App,Computer
.
I'd like to have it in the following order: Computer,App,Installed
.
Upvotes: 13
Views: 38899
Reputation: 1
A more universal way to change the order is using the Select-Object cmdlet with the list of properties in the required order.
See the example:
PS> $ObjectList = 1..3 |
% {New-Object psobject -Property @{P2="Object $_ property P2"; P1="Object $_ property P1"}}
PS> $ObjectList
P2 P1
-- --
Object 1 property P2 Object 1 property P1
Object 2 property P2 Object 2 property P1
Object 3 property P2 Object 3 property P1
PS> $ObjectList | Select-Object P1,P2
P1 P2
-- --
Object 1 property P1 Object 1 property P2
Object 2 property P1 Object 2 property P2
Object 3 property P1 Object 3 property P2
The full form of these commands is the following:
$ObjectList = 1..3 |
ForEach-Object -Process {New-Object -TypeName psobject -Property @{P2="Object $_ property P2"; P1="Object $_ property P1"}}
$ObjectList | Select-Object -Property P1,P2
Upvotes: 0
Reputation: 24816
Format-Table
it's a good solution when you need to display your object fields in a specific order, but it will change the obect and you won't be able to pipe your object, for example when exporting to csv (Export-Csv
).
In the case you just want to change "the order of the fields in the object" use Select-Object
. This will preserve object type and fields, and still you will be able to pipe the object to other cmdlets.
Upvotes: 6
Reputation: 68243
Powershell V3 added a type accelerator for [PSCustomObject] that creates objects using an ordered hash table, so the properties stay in the order they're declared:
[PSCustomObject] @{
Computer=$computer.hostname
App=$app.appname
Installed=$installed
}
Upvotes: 24
Reputation: 201602
If you want to ensure the output of an object occurs in a certain order i.e. formatted a certain way then use PowerShell's formatting commands.
$obj = [pscustomobject]@{Computer=$computer.hostname;App=$app.appname;Installed=$installed}
$obj | Format-Table Computer,App,Installed
What's more you can better control the output e.g.:
$obj | Format-Table Computer,App,Installed -AutoSize
Or control field width & alignment:
$obj | Format-Table @{label='Computer';expression={$_.Computer};width=20;alignment='right'},App,Installed
Frankly I think it is a better practice to use the formatting commands to get the output order you want rather than to rely upon the order in which the properties are created.
Upvotes: 19
Reputation: 12323
The problem is that you're adding the properties using a hashtable, and hashtables don't preserve order. You can do one of two things:
1. Add the properties in a manner that will set the order (the last line is to output the object to the pipeline):
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $computer.hostname
$obj | Add-Member -MemberType NoteProperty -Name App -Value $app.appname
$obj | Add-Member -MemberType NoteProperty -Name Installed -Value $installed
$obj
2. Determine the order at the time you output the object to the pipeline using Select-Object:
New-Object PSObject -Property @{
Computer=$computer.hostname
App=$app.appname
Installed=$installed
} | select Computer,App,Installed
Which one is preferable depends on how much you'll be working with the object. If, as your question implies, you're only using the PSObject in order to display the information in tabular format, the second method is quicker. If you're going to output the object multiple times in different parts of the script, the first method allows you to simply output it as $obj
rather than having to pipe to select every time.
Note also that the second method can be split up like this if you don't want to output the object immediately after populating it:
$obj = New-Object PSObject -Property @{
Computer=$computer.hostname
App=$app.appname
Installed=$installed
}
[...do other stuff...]
$obj | select Computer,App,Installed
Upvotes: 6