Default sort property

This topic contains 7 replies, has 5 voices, and was last updated by  vrshell 2 weeks, 2 days ago.

  • Author
    Posts
  • #84908

    vrshell
    Participant

    PS 5.1 on Win10 1709.

    How is the default sort property specified for an object? I've googled around and found several copies of the same instance where this question was asked, but either the answer isn't the answer, or I don't know what I'm looking at (probability of the latter approaches 100%).

    For example,

    Get-ChildItem | Sort-Object

    sorts on name, even though no sort property was specified.

    And the help for Sort-Object says this:

    If you do not specify properties, the cmdlet sorts based on default properties for the object type.

    The one answer I found for this referred to the FileSystem.Format.ps1xml file, but I don't see anything in there that relates to sorting and/or ordering. I see that Name is specified as the WideEntry; does sorting also use that by default?

    In short, where is Sort getting its information for the default sort property for an object?

  • #84916

    Curtis Smith
    Participant

    Looks like it's actually stored as part of types.ps1xml, not the FileSystem.Format.ps1xml

    "C:\Windows\System32\WindowsPowerShell\v1.0\typesv3.ps1xml"
    "C:\Windows\System32\WindowsPowerShell\v1.0\types.ps1xml"

      ‹Type›
        ‹Name›System.IO.DirectoryInfo‹/Name›
        ‹Members›
          ‹CodeProperty›
            ‹Name›Mode‹/Name›
            ‹GetCodeReference›
              ‹TypeName›Microsoft.PowerShell.Commands.FileSystemProvider‹/TypeName›
              ‹MethodName›Mode‹/MethodName›
            ‹/GetCodeReference›
          ‹/CodeProperty›
          ‹ScriptProperty›
            ‹Name›BaseName‹/Name›
            ‹GetScriptBlock›
              $this.Name
            ‹/GetScriptBlock›
          ‹/ScriptProperty›      
          ‹MemberSet›
            ‹Name›PSStandardMembers‹/Name›
            ‹Members›
              ‹NoteProperty›
                ‹Name›DefaultDisplayProperty‹/Name›
                ‹Value›Name‹/Value›
              ‹/NoteProperty›
            ‹/Members›
          ‹/MemberSet›
        ‹/Members›
      ‹/Type›
    
  • #84929

    vrshell
    Participant

    My apologies for what my wife calls male pattern blindness, but where? In the segment you included, I see only a DefaultDisplayProperty, not a DefaultSortProperty (or anything similar). Nor do I see anything in either of the full .ps1xml files.

    Further, on System.IO.FileInfo, e.g., there is no DefaultDisplayProperty, it is instead DefaultDisplayPropertySet and consists of three properties (LastWriteTime,Length,Name), while default sort uses only name. So I don't see how DefaultDisplayPropertySet could be used as the DefaultSortProperty.

  • #84959

    Alex Aymonier
    Participant
    $this.Name
  • #84992

    vrshell
    Participant

    That is the script block for the BaseName ScriptProperty. It's defining how BaseName is defined for directories (that script block is more elaborate for System.IO.FileInfo). I don't see how it has anything to do with the default sort property.

  • #85094

    js
    Participant

    Something like this used to trick me up. I'm only sending one property, but sort can't figure out to sort it (it returns one item), unless I do select -expand or sort -u filename. Maybe open source will fix it.

    ls -r *.bat | select-string netsh | select filename | sort -u
    
  • #85175

    Rob Simmers
    Participant

    This was a fun rabbit hole to go down, but my thought was that this was something defined as a PSStandardMember. This data is hidden by default, so it takes some digging to get which is discussed by Mr. Snover here: https://blogs.msdn.microsoft.com/powershell/2010/02/18/psstandardmembers-the-stealth-property/

    You can see if this is defined in the object like so:

    PS C:\Users\Rob> $obj.PSStandardMembers.DefaultKeyPropertySet
    
    
    ReferencedPropertyNames : {Age, Name}
    MemberType              : PropertySet
    Value                   : DefaultKeyPropertySet {Age, Name}
    TypeNameOfValue         : System.Management.Automation.PSPropertySet
    Name                    : DefaultKeyPropertySet
    IsInstance              : True
    
    ReferencedPropertyNames : {Age, Name}
    MemberType              : PropertySet
    Value                   : DefaultKeyPropertySet {Age, Name}
    TypeNameOfValue         : System.Management.Automation.PSPropertySet
    Name                    : DefaultKeyPropertySet
    IsInstance              : True
    
    ReferencedPropertyNames : {Age, Name}
    MemberType              : PropertySet
    Value                   : DefaultKeyPropertySet {Age, Name}
    TypeNameOfValue         : System.Management.Automation.PSPropertySet
    Name                    : DefaultKeyPropertySet
    IsInstance              : True
    

    You can also use the same method of setting the DefaultKeyPropertySet (default sort) as DefaultDisplayPropertySet:

    #Create data to play with
    $obj = @()
    $obj += [pscustomobject]@{Name = "Alice";Age = '23';Hobby='Football'}
    $obj += [pscustomobject]@{Name = "Jim";Age = '19';Hobby='Pool'}
    $obj += [pscustomobject]@{Name = "Sam";Age = '29';Hobby='Curling'}
    
    #Define Sort by Age then Name
    $defaultSort = @('Age', 'Name')
    #Define default properties to show in object (hide Hobby)
    $defaultProperties = @('Name', 'Age')
    
    #Define the DefaultKeyPropertySet: https://stackoverflow.com/questions/46715431/how-to-access-psobject-defaultkeypropertyset-details-in-net-with-c-sharp
    $defaultSortSet = New-Object System.Management.Automation.PSPropertySet('DefaultKeyPropertySet',[string[]]$defaultSort)
    #Lots of blogs on this, setting the default displayed properties
    $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultProperties)
    
    #Add the PSStandardMembers
    $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet,$defaultSortSet)
    
    $obj | Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $PSStandardMembers
    
    #Show the PSStandardMembers of the object: https://blogs.msdn.microsoft.com/powershell/2010/02/18/psstandardmembers-the-stealth-property
    $obj |Get-Member PSStandardMembers -Force
    
    #   TypeName: System.Management.Automation.PSCustomObject
    
    #Name              MemberType Definition                                                          
    #----              ---------- ----------                                                          
    #PSStandardMembers MemberSet  PSStandardMembers {DefaultDisplayPropertySet, DefaultKeyPropertySet}
    
    #Object show ordered as order of creation
    $obj
    
    #Name  Age
    #----  ---
    #Alice 23 
    #Jim   19 
    #Sam   29
    
    
    #Default sorted by Age
    $obj | Sort
    
    #Name  Age
    #----  ---
    #Jim   19 
    #Alice 23 
    #Sam   29
    
    
    #Override default sort by defining property Name
    $obj | Sort -Property Name
    
    #Name  Age
    #----  ---
    #Alice 23 
    #Jim   19 
    #Sam   29 
    
    

    If anyone is looking for a good blog idea, I was working on how to enumerate all PSStandardMembers and what other fun could be had.

  • #85283

    vrshell
    Participant

    I hate to be a broken record, but…

    The DefaultDisplayProperty[Set] is visible in the types.ps1xml file. We've already seen it (Curtis' post above). (It is nice to know that there's a PS way to see that information as well, so thanks for that.)

    However, neither of those have anything to do with the default sort property (which, from your reply, would seem to be DefaultKeyProperty[Set]). That doesn't exist in the types.ps1xml file (for either FileInfo or DirectoryInfo; the only occurrence is for HistoryInfo).

    In your first block above, you don't show what $obj is, so we don't know what object it's showing the DefaultKeyPropertSet for, but it doesn't appear to be for Get-ChildItem, at least from my testing.

    PS C:\users\vrice\Downloads> $obj = get-childitem .\epm.exe
    PS C:\users\vrice\Downloads> $obj
    
    
        Directory: C:\users\vrice\Downloads
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        11/1/2017   3:24 PM       38025088 epm.exe
    
    
    PS C:\users\vrice\Downloads> $obj.PSStandardMembers.DefaultKeyProperty
    PS C:\users\vrice\Downloads> $obj.PSStandardMembers.DefaultKeyPropertySet
    PS C:\users\vrice\Downloads>

    And yet Get-ChildItem sorts automatically on name.

    We're still not at the bottom of the rabbit hole. 🙂

You must be logged in to reply to this topic.