Default display of objects in the Windows PowerShell console
In PowerShell you have format.ps1xml documents. These are used to simplify what and how object data is shown to the end user. A simple default example would be Get-Process
. If no changes are requested it will by default show the following property set..
Get-Process | Select -first 1
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName
------- ------ ----- ----- ----- ------ -- -- -----------
172 12 197960 208444 309 1,464.52 701036 1 7zG
However a System.Diagnostics.Process
has many more properties associated to it (Get-Process | gm -MemberType Property
). Also, the example above has NPM(K)
which is not a real property. You can see how it is derived to looking at the following format file: DotNetTypes.format.ps1xml (Common location to find this would be: C:\Windows\System32\WindowsPowerShell\v1.0)
<View>
<Name>process</Name>
<ViewSelectedBy>
<TypeName>System.Diagnostics.Process</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
...
<TableColumnHeader>
<Label>NPM(K)</Label>
<Width>7</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
...
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
....
<TableColumnItem>
<ScriptBlock>[long]($_.NPM / 1024)</ScriptBlock>
</TableColumnItem>
....
</TableRowEntries>
</TableControl>
</View>
So that column is actually a calculated property based on NPM. Most of the common cmdlets do things like this as a favour to the end user (citation needed). The raw data is still there if you know how to find it but the default output formatting is supposed to just be a quick glance of the important / familiar information.
I could see some users getting confused trying to request a property that does not exist base on the table they got initially. (Get-Process)."NPM(K)"
would show nothing.
Custom format.ps1xml
I have a module that I am making that is based on scraping a local buy and sell site. A search listing will have multiple properties like information about the number of search results, associated URL of the search and the actual posts or listing associated with the search.
Trying my best to get to the heart of the problem I have a method called .hasMorePages()
. If there is more listing to be view then what is on this search this method will return true. This is not normally displayed in output as it is a method and not a property. I can use a custom format.ps1xml file to make this show up. The following is just a snippet of the larger file.
.....
<ListItem>
<Label>Has More Pages</Label>
<ScriptBlock>if($_.hasMorePages()){"Yes"}else{"No"}</ScriptBlock>
</ListItem>
....
So you would see something like this in the standard output for the search variable:
Requested URL : .....obfuscated
FirstListingResultIndex : 1
LastListingResultIndex : 20
TotalNumberOfSearchResults : 84
Has More Pages : Yes
Listings : {Toys/Games for Sale, RARE HiltonHeadopoly MONOPOLY Game with
Hilton Head Landmarks, Clue and Monopoly (Halifax version),
Assorted Monopoly Games-Various Prices...}
So Has More Pages : Yes
shows exactly how I defined it. I am worried that this violates some sort of "Princial of least surprise". If you tried to isolate that variable it would not work. $searchListing."Has More Pages"
would be null as that is not the property. So it looks nice in output but that is not the real property. This is just an example I made for the purpose of writing this question. This could be mitigated by making an alias property of the same name to point to hasmorepages()
but that would show a boolean and not the yes/no
In the case of Get-Process
I expect this to be true as I am familiar with how PowerShell does this and works. I would not expect the same for custom cmdlets.
As cool as making custom formatting directives are is there some sort of mantra I should try to follow where I can try and keeps things simple initially while not hiding or confusing users about where the real properties and data are?