PSStandardMembers – The Stealth Property

PSStandardMembers – The Stealth Property

  • Comments 4

Today I got the question

I’ve looked into all of my.format.ps1xml files but I can’t find out where Format-List is getting its default view for, say, System.Diagnostics.Process:

PS> ps |select -first 1 |fl

Id      : 7616
Handles : 543
CPU     : 10.6860685
Name    : CmdletDesigner

How does it know it should display just these four properties?
It seems there isn’t any ListControl view selected by this type within those formatting files...

Excellent question!  Let’s pick behind the curtain and see how it works.  When an object gets to one of our formatting commands, we use its type to look and see if there is a VIEW defined for it.  These views are defined in our formatting files in $PSHOME directory.  They have filenames like xxx.Format.ps1xml .  If we find it, we use it.  If we don’t find it, we look to see whether this type has a DefaultDisplayPropertySet defined.  If it does, we use it.  If it doesn’t we emit all the properties either as a table or a list depending upon how many properties there are.

 

But wait a minute – let’s go back and look at this DefaultDisplayPropertySet – what’s that all about?  If you’ve been using PowerShell a while, you’ll realize that PowerShell uses a type mashup system.  Mashups are really just an identity space and a mechanism for 3rd parties to add addition information into an identity space.  For map mashups, the identity space is latitude/longitude and a mechanism for someone to provide the lat/long for all the Starbucks in the world.  For PowerShell, we use TYPEs as an identity space and then have various mechanisms for 3rd parties to add extra information.  One of those mechanisms is TYPE files (e.g. $pshome/types.ps1xml ).  If you take a look at the file, you’ll see that we have a set of entries which are keyed off of a typename and can add extra information.  If you search for System.Diagnostics.Process – you’ll see a bunch of stuff.   One of the things you can add to a type is a MemberSet

 

One of the things you’ll see is a super double secret MemberSet called PSStandardMembers.   This is a hidden memberset that PowerShell uses for it’s own purposes.  In that memberset, you (we) can define something called DefaultDisplayPropertertySet which provides a set of properties that should be displayed if there isn’t a view defined.  Let me show you that it is really there (you can follow along at home):

PS> $x = Get-Process |Select -First 1
PS> $x |Format-List

Id      : 7616
Handles : 543
CPU     : 10.7172687
Name    : CmdletDesigner

PS> # Let me prove to you that it is hidden
PS> $x |Get-Member PSStandardMembers


PS> # It's really there, just hidden.  You can show hidden things using -Force
PS> $x |Get-Member PSStandardMembers -Force

   TypeName: System.Diagnostics.Process

Name              MemberType Definition
----              ---------- ----------
PSStandardMembers MemberSet  PSStandardMembers {DefaultDisplayPropertySet}

PS> $x.PSStandardMembers
PSStandardMembers {DefaultDisplayPropertySet}


PS> $x.PSStandardMembers.DefaultDisplayPropertySet

ReferencedPropertyNames : {Id, Handles, CPU, Name}
MemberType              : PropertySet
Value                   : DefaultDisplayPropertySet {Id, Handles, CPU, Name}
TypeNameOfValue         : System.Management.Automation.PSPropertySet
Name                    : DefaultDisplayPropertySet
IsInstance              : False


PS> $x.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames
Id
Handles
CPU
Name
PS>

 

Now it really isn’t secret we just haven’t talked about it much.  It is documented @ MSDN HERE .

PSStandardMembers is used for a number of things in addition to DefaultDisplayProperties.  In particular, it is used to control object serialization.  You can find out more about that in my blog entry HERE.

 

Enjoy!

Jeffrey Snover [MSFT]
Distinguished Engineer
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Comment
  • Please add 3 and 4 and type the answer here:
  • Post
  • Great post. Thanks for the background.

    I wonder if this will make it into Bruce's second edition...

  • $ts=[timespan]0

    # empty timespan object

    $ts=[timespan]1

    # timespan object set to one tick.

    $ts=[timespan]1d

    # timespan object set to 1 day.

    What are the other time operators?  We have gb,kb, tb, etc.  What about teh rest of the time operators?  Where is this documented.

    Good for a blog maybe.

  • Hi Jeffrey,

    info about PSStandardMembers is quite interesting, however Get-Member -FORCE is even more interesting :)

    Martin

  • I still really want this sort of configuration information to be settable for both objects returned by cmdlets and custom objects created using New-Object from PowerShell itself without the need for a ps1xml file. It makes much more sense to me to have this information defined in a module or function in PowerShell script right next to the definition of the object, not in an external ps1xml file. Part of this used to work in PowerShell 1.0 (http://poshoholic.com/2008/07/05/essential-powershell-define-default-properties-for-custom-objects/) but now that's broken. Please consider fixing the broken issue and supporting defining the rest of this for a future release of PowerShell. I'd love to see cmdlets or a DSL allow you to define this inline in PowerShell script files.

    Also something that is still unclear in this area is how do you define an object that rehydrates with all properties intact, not as a deserialized object? I can create simple custom objects with properties containing strings and integers and when I Export-Clixml and then Import-Clixml, the object comes back with the type names prefixed with "Deserialized.".  I want a method to do this same task without the "Deserialized." prefix.

Page 1 of 1 (4 items)