Does PSCustomObject have an order in which its displayed to the console?

530 Views Asked by At

Good morning peeps,

Im a big fan of making a selection from values that are returned from listed items. So, I was expirementing with making a selection out of the values returned from C:\Users, which is input into a [PSCustomObject] type, but noticed something off. I can list the selection into the [PSCustomObject] just fine like so:

[array]$Userlist = Get-ChildItem C:\users | Sort-Object -Property LastWriteTime -Descending
        for($i=0; $i -lt $UserList.BaseName.count; $i++){
        [PSCustomObject]@{
                'Profile Name'  = "$($i): $($UserList.BaseName[$i])"
                '  Full Path  ' = $UserList.FullName[$i] 
                'Modified Time' = $UserList.LastWriteTime[$i] 
                        }
                    }

#Output:
Profile Name   Full Path      Modified Time        
------------ -------------    -------------        
0: Abraham   C:\users\Abraham 4/11/2021 10:26:58 PM
1: Public    C:\users\Public  3/28/2021 8:51:28 AM 

..but, when I try to make a selection simply by adding a Read-Host at the end of the script, I get that prompt first:

[array]$Userlist = Get-ChildItem C:\users | Sort-Object -Property LastWriteTime -Descending
        for($i=0; $i -lt $UserList.BaseName.count; $i++){
        [PSCustomObject]@{
                'Profile Name'  = "$($i): $($UserList.BaseName[$i])"
                '  Full Path  ' = $UserList.FullName[$i] 
                'Modified Time' = $UserList.LastWriteTime[$i] 
                        }
                    }
                
              
$ii = Read-Host -Prompt "Enter The Users Number to Delete"
$i  = $ii -split " "
      ""
    foreach($profile in $Userlist.baseName[$i]){
        ""
        "Selection: $profile"
        }

#output
Enter The Users Number to Delete: 1    <------ Here its asking first before displaying.
Profile Name   Full Path      Modified Time        
------------ -------------    -------------        
0: Abraham   C:\users\Abraham 4/11/2021 10:26:58 PM
1: Public    C:\users\Public  3/28/2021 8:51:28 AM 


Selection: Public

Am I missing something? Why is my Read-Host being prompted before my top object is displayed? Id like to see the selection before i choose lol

Is there an order in which it's displayed?

1

There are 1 best solutions below

4
On BEST ANSWER

A similar example of how the formatting system can surprise users.

Have a simple CSV

@'
OneProperty
test
'@ | ConvertFrom-Csv

OneProperty
-----------
test  

And another

@'
OneProperty,TwoProperty
test1,test2
'@ | ConvertFrom-Csv

OneProperty TwoProperty
----------- -----------
test1       test2  

Everything is perfect, as expected.

But running these together

@'
OneProperty
test
'@ | ConvertFrom-Csv

@'
OneProperty,TwoProperty
test1,test2
'@ | ConvertFrom-Csv

OneProperty
-----------
test       
test1      

Where is the second property? Well, the first object to hit the formatting system is what determines the properties. Powershell won't check each item because that could be a big performance hit. However, if you force the output to the formatter with Out-Host, Out-Default, or any of the Format-* cmdlets..

@'
OneProperty
test
'@ | ConvertFrom-Csv | Out-Default

@'
OneProperty,TwoProperty
test1,test2
'@ | ConvertFrom-Csv | Out-Default


OneProperty
-----------
test       


OneProperty TwoProperty
----------- -----------
test1       test2   

We can see both are shown completely. Simply put, the Read-Host cmdlet just beats your pipeline output to the formatting system.

You can also surround commands/sections of code with sub-expression and pipe it versus assigning to a variable.

$(for($i=0; $i -lt $UserList.BaseName.count; $i++){
    [PSCustomObject]@{
        'Profile Name'  = "$($i): $($UserList.BaseName[$i])"
        '  Full Path  ' = $UserList.FullName[$i] 
        'Modified Time' = $UserList.LastWriteTime[$i] 
    }
}) | Out-Default