2

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?

  • I was not sure how to get this smaller without assuming that people knew about the concepts that I am talking about. If this could be made more terse I would love to do so. – Matt Jan 8 '18 at 17:31
  • I have no issues with downvotes but if someone can suggest what might be wrong about the question, so that I can ask better questions here, that would be appreciated. – Matt Jan 8 '18 at 19:51
2

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?

Generate a help file for your module using a tool such as PlatyPS:

PlatyPS provides a way to:

Write PowerShell External Help in Markdown Generate markdown help (example) for your existing modules Keep markdown help up-to-date with your code

And add some text to the help file:

Which describes how to see what is really there:

The default formatter can mislead, but format-list or using get-member commandlet will list all the properties.

and use the PSScriptAnalyzer for further information.

References

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.