Welcome PowerShell User! This recipe is just one of the hundreds of useful resources contained in the PowerShell Cookbook.

If you own the book already, login here to get free, online, searchable access to the entire book's content.

If not, the Windows PowerShell Cookbook is available at Amazon, or any of your other favourite book retailers. If you want to see what the PowerShell Cookbook has to offer, enjoy this free 90 page e-book sample: "The Windows PowerShell Interactive Shell".

3.17 Define Custom Formatting for a Type

Problem

You want to emit custom objects from a script and have them formatted in a specific way.

Solution

Use a custom format extension file to define the formatting for that type, followed by a call to the Update-FormatData cmdlet to load them into your session:

$formatFile = Join-Path (Split-Path $profile) "Format.Custom.Ps1Xml"
Update-FormatData -PrependPath $typesFile

If a file-based approach is not an option, use the Formats property of the [Runspace]::DefaultRunspace.InitialSessionState type to add new formatting definitions for the custom type.

Discussion

When PowerShell commands produce output, this output comes in the form of richly structured objects rather than basic streams of text. These richly structured objects stop being of any use once they make it to the screen, though, so PowerShell guides them through one last stage before showing them on screen: formatting and output.

The formatting and output system is based on the concept of views. Views can take several forms: table views, list views, complex views, and more. The most common view type is a table view. This is the form you see when you use Format-Table in a command, or when an object has four or fewer properties.

As with the custom type extensions described in Recipe 3.16, PowerShell supports both file-based and in-memory updates of type formatting definitions.

The simplest and most common way to define formatting for a type is through the Update-FormatData cmdlet, as shown in the Solution. The Update-FormatData cmdlet takes paths to Format.ps1xml files as input. There are many examples of formatting definitions in the PowerShell installation directory that you can use. To create your own formatting customizations, use these files as a source of examples, but do not modify them directly. Instead, create a new file and use the Update-FormatData cmdlet to load your customizations.

For more information about the features supported by these formatting XML files, type Get-Help about_format.ps1xml.

In addition to file-based formatting, PowerShell makes it possible (although not easy) to create formatting definitions from scratch. Example 3-16 provides a script to simplify this process.

Example 3-16. Add-FormatData.ps1
##############################################################################
##
## Add-FormatData
##
## From PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################

<#

.SYNOPSIS

Adds a table formatting definition for the specified type name.

.EXAMPLE

PS > $r = [PSCustomObject] @{
    Name = "Lee";
    Phone = "555-1212";
    SSN = "123-12-1212"
}
PS > $r.PSTypeNames.Add("AddressRecord")
PS > Add-FormatData -TypeName AddressRecord -TableColumns Name, Phone
PS > $r

Name Phone
---- -----
Lee  555-1212

#>

param(
    ## The type name (or PSTypeName) that the table definition should
    ## apply to.
    $TypeName,

    ## The columns to be displayed by default
    [string[]] $TableColumns
)

Set-StrictMode -Version 3

## Define the columns within a table control row
$rowDefinition = New-Object Management.Automation.TableControlRow

## Create left-aligned columns for each provided column name
foreach($column in $TableColumns)
{
    $rowDefinition.Columns.Add(
        (New-Object Management.Automation.TableControlColumn "Left",
            (New-Object Management.Automation.DisplayEntry $column,"Property")))
}

$tableControl = New-Object Management.Automation.TableControl
$tableControl.Rows.Add($rowDefinition)

## And then assign the table control to a new format view,
## which we then add to an extended type definition. Define this view for the
## supplied custom type name.
$formatViewDefinition =
    New-Object Management.Automation.FormatViewDefinition "TableView",$tableControl
$extendedTypeDefinition =
    New-Object Management.Automation.ExtendedTypeDefinition $TypeName
$extendedTypeDefinition.FormatViewDefinition.Add($formatViewDefinition)

## Add the definition to the session, and refresh the format data
[Runspace]::DefaultRunspace.InitialSessionState.Formats.Add($extendedTypeDefinition)
Update-FormatData