Using the PowerShell formatting system to your advantage
By Jos Koelewijn (@Jawz_84)
About Format and Type data
PowerShell has two main systems to determine what to show in the default view for a given type:
The Format system
The Type system
In that order; the Formatting system takes precedence over formatting info in the Type system.
Format data is completely centered around how a certain Type should be displayed. Type data is all about defining extra properties and methods, but also accomodates a DefaultDisplayProperty
and DefaultDisplayPropertySet
property that can be set.
For a lot of types, PowerShell has default Format and Type data built in. Many modules come with their Format and Type data as well. This information is applied per Type. Any time an object of a certain type is emitted to the console, formatting information is matched from the Format and Type system by Type name.
You can view currently loaded Format and Type data with Get-FormatData
and Get-TypeData
.
All related commands can be found with this line:
Add or change Format data
Changing Format data can only be done by file import. Update-FormatData
only accepts ps1xml
-file data from a path. The file format is documented in the help of the command, I won't cover that here. The authoring experience could be improved. An easy way to obtain a 'template' if you will, is by exporting the formatting data for an existing type, by using Export-FormatData -Typename 'TypeIWantToExport'
. Imported Format data will be lost at the end of the session.
Add or change Type data
Type data can be changed by file import as well, but less known is the fact you can also use Update-TypeData
with parameters. For example to add a Property to a Type, you can Use it with -Force
when you need to overwrite existing data. Imported Type data will also be lost at the end of the session, or you can choose to remove Type data from the session with Remove-TypeData
.
How to use this to our advantage
Types with Format data loaded (the hard way)
Types for which Format data is already present in the session, like [System.TimeSpan]
, we need to export that data to a file, change it, and import it again.
This is the default view for New-TimeSpan
(Output Type is [System.TimeSpan]
):
First, we get the Format data:
We can now go about various ways to view this ps1xml
-file. You can edit it with your favourite code editor or use PowerShell to do some reconnaissance:
We see there are three views available, one for List, one for Table and one for Wide. These will be used by Format-List
, Format-Table
and Format-Wide
respectively. When none of these is used, PowerShell will use the List view or Table view, depending on the amount of properties to display. Four or less properties will result in Table view, more than four properties in List view.
Let's say we want to edit the List view for [System.TimeSpan]
. That's this part of the file:
We can see there are a lot of ListItems defined. Let's say we want to remove half of them, keeping only Days
, Hours
, Minutes
and Seconds
. Remove the other blocks of xml code, save the file, and import it back to the session with this:
Now, New-TimeSpan
should have a condensed default view. Let's test it out:
At the time of writing, there is an open issue to expand Update-FormatData
with parameters to be more like Update-TypeData
. For now, there is no other way. This is the way.
Types without Format data loaded (the easy way)
Types for which there is no preexisting Format data in the current session are the easiest because there we can directly set the default view by using the DefaultDisplayPropertySet
parameter of Update-TypeData
.
An example with a PSCustomObject
:
A very simple object with only three properties, that we give a Type name of 'MyType', by specifying PSTypeName in the PSCustomObject.
Let's set the default display property set, to change which properties are shown by default:
Even though there is a property C, it is now hidden.
Note: When you want to overwrite existing Type data, you need to use the
-Force
switch withUpdate-TypeData
, or it will throw an error.
You can check if your session currently has Format data for your target Type like this:
If it does not return anything, there is no Format data for MyType
.
Real world applications
You can define a default set of properties to show for objects you created, right there in the code where the object is defined. Be it a PowerShell class, a C# class, or a PsCustomObject with the PSTypeName trick.
When the object has nested objects, you can do fun things with them, like digging up that nested data, and showing them at the top level. See this blog post about Azure Policies for an example of that.
The two things I like most about this, is that it does not require you to author a lengthy XML file, and your formatting information can sit right next to your Type definition.
I hope you found this useful. Please feel free to reach out to me if you have questions. You can ping me on Twitter, or drop me a message on the PowerShell Discord server.
Last updated