none
Change default formatting of output from PowerShell script RRS feed

  • Question

  • I have a PowerShell script intended for testing a web application. It outputs various types of objects that contain data parsed from HTTP responses. I want the script to display this data by default, so that I can see what it is doing, and I also want to be able to capture the output to a variable so that I can examine the properties of the objects in more detail.

    When I am not capturing the output of the script to a variable or piping it to a cmdlet, PowerShell 5.1 appears to format the output as if I had piped it to Format-Table, which chooses the columns of the table based on the properties of the first object. My problem is that the other objects have entirely different properties and Format-Table generally does not display them at all.

    I can simulate the behavior by using this command:

    @( [System.Tuple]::Create(10); [System.Collections.Generic.KeyValuePair[[Int],[Int]]]::new(20, 21); ) | Format-Table

    The output is:

    Item1 Length
    ----- ------
       10      1

    That is, the Key and Value properties of the KeyValuePair object do not appear at all. The same happens if I omit the Format-Table invocation. In contrast, if I pipe the objects to Format-List, then the output is more useful:

    Item1  : 10
    Length : 1
    
    Key   : 20
    Value : 21
    

    How does PowerShell decide to use Format-Table to format the output?

    Can I put something in the script to make PowerShell default to Format-List instead, while retaining the ability to pipe the original objects to other cmdlets?

    Wednesday, January 9, 2019 4:31 PM

All replies

  • PowerShell outputs objects (not text), so why does the formatting of the output objects matter?

    If you want a specific format, collect the properties of the objects you want, output them as a list of custom objects, and format them afterwards.


    -- Bill Stewart [Bill_Stewart]


    Wednesday, January 9, 2019 5:09 PM
    Moderator
  • If you analyze the code you will see that it is bogus.  You are trying to make a table out of two dissimilar items in an array. The first item returned will be the one that decides the properties.

    PS D:\scripts> @(
    >>     [System.Tuple]::Create(10)
    >>     [System.Collections.Generic.KeyValuePair[[Int], [Int]]]::new(20, 21)
    >> )
    
    Item1 Length
    ----- ------
       10      1
    
    
    
    PS D:\scripts> [System.Tuple]::Create(10)
    
    Item1 Length
    ----- ------
       10      1
    
    
    PS D:\scripts> [System.Collections.Generic.KeyValuePair[[Int], [Int]]]::new(20, 21)
    
    Key Value
    --- -----
     20    21
    
    
    PS D:\scripts>

    Format-List formats each object separately.

    PS D:\scripts> @(
    >>     [System.Tuple]::Create(10)
    >>     [System.Collections.Generic.KeyValuePair[[Int], [Int]]]::new(20, 21)
    >> ) | Format-List
    
    
    Item1  : 10
    Length : 1
    
    Key   : 20
    Value : 21

    Do not create arrays of dissimilar objects if you want consistent output Or. As Bill noted, create a custom code block to format the results as you want.


    \_(ツ)_/

    Wednesday, January 9, 2019 5:17 PM
  • If I pipe the output of the script to Format-List, then I get the format that I want.

    However, it would be more convenient if that happened automatically. PowerShell already implicitly formats the objects and I'd like to know if that can be controlled or tricked somehow.

    It seems that, if the first output object is a dummy Hashtable like @{a=1}, then PowerShell formats that as an IEnumerable<DictionaryEntry> table and formats the subsequent objects as if by Format-List. That would be handy except the dummy object at the start of the output looks ugly. An empty Hashtable unfortunately does not have the same effect.

    Wednesday, January 9, 2019 5:19 PM
  • I refer the honorable gentleman to my first reply posted some minutes ago.

    -- Bill Stewart [Bill_Stewart]

    Wednesday, January 9, 2019 5:22 PM
    Moderator
  • No.  The formatting choice is determined by the first element returned.  If you look in the format file for the objects you are using you will see the formats applied by object type.  The object type of an array will always force the selection of a table if the first object in the array does not have a format specified that is different.

    See: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_format.ps1xml?view=powershell-6


    \_(ツ)_/

    Wednesday, January 9, 2019 5:25 PM
  • The actual types of objects output by the script are:

    1. System.Management.Automation.PSCustomObject
    2. System.Management.Automation.PSCustomObject
    3. System.Management.Automation.PSCustomObject
    4. System.Management.Automation.PSCustomObject
    5. Microsoft.PowerShell.Commands.WebResponseObject
    6. Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
    7. System.Net.HttpWebResponse

    where each PSCustomObject is the result of Invoke-RestMethod.

    Do you then recommend making the script invoke Format-List on its own? With perhaps a SwitchParameter to suppress this formatting.

    Wednesday, January 9, 2019 5:25 PM
  • I'll go ahead and repeat my first message...

    PowerShell outputs objects (not text), so why does the formatting of the output objects matter?

    If you want a specific format, collect the properties of the objects you want, output them as a list of custom objects, and format them afterwards.


    -- Bill Stewart [Bill_Stewart]

    Wednesday, January 9, 2019 5:57 PM
    Moderator