Investigating PowerShell Console Output

by Mar 24, 2021

When you see results from commands in the PowerShell console, typically only part of the information is displayed. To see the complete information, you need to send it to Select-Object and explicitly select all properties using the “*” wildcard:

 
PS> Get-CimInstance -ClassName Win32_BIOS


SMBIOSBIOSVersion : 1.7.1
Manufacturer      : Dell Inc.
Name              : 1.7.1
SerialNumber      : 4ZKM0Z2
Version           : DELL   - 20170001




PS> Get-CimInstance -ClassName Win32_BIOS | Select-Object -Property *


Status                         : OK
Name                           : 1.7.1
Caption                        : 1.7.1
SMBIOSPresent                  : True
Description                    : 1.7.1
InstallDate                    : 
BuildNumber                    : 
CodeSet                        : 
IdentificationCode             : 
LanguageEdition                : 
Manufacturer                   : Dell Inc.
OtherTargetOS                  : 
SerialNumber                   : 4ZKM0Z2
SoftwareElementID              : 1.7.1
SoftwareElementState           : 3
TargetOperatingSystem          : 0
Version                        : DELL   - 20170001
PrimaryBIOS                    : True
BiosCharacteristics            : {7, 9, 11, 12...}
BIOSVersion                    : {DELL   - 20170001, 1.7.1, Dell - 10000}
CurrentLanguage                : enUS
EmbeddedControllerMajorVersion : 255
EmbeddedControllerMinorVersion : 255
InstallableLanguages           : 1
ListOfLanguages                : {enUS}
ReleaseDate                    : 28.12.2020 01:00:00
SMBIOSBIOSVersion              : 1.7.1
SMBIOSMajorVersion             : 3
SMBIOSMinorVersion             : 1
SystemBiosMajorVersion         : 1
SystemBiosMinorVersion         : 7
PSComputerName                 : 
CimClass                       : root/cimv2:Win32_BIOS
CimInstanceProperties          : {Caption, Description, InstallDate, Name...}
CimSystemProperties            : Microsoft.Management.Infrastructure.CimSystemProperties 
 

That’s because PowerShell contains logic that automatically selects only the most important properties of objects in an effort to let you focus on what is important. To better understand how that works, here is some sample code that explores the data returned by Get-Process. To investigate other cmdlets, replace “Get-Process” in the code with the name of another cmdlet:

Install-Module -Name PSCommandDiscovery -Scope CurrentUser -Verbose

The code determines the data type emitted by the cmdlet, then finds the *.format.ps1xml file that defines the view for this data type, and returns the first 20 lines of that definition:

 
             </ViewSelectedBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Label>Handles</Label>
                        <Width>7</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>NPM(K)</Label>
                        <Width>7</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>PM(K)</Label>
                        <Width>8</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>WS(K)</Label>
            </ViewSelectedBy>
            <GroupBy>
                <PropertyName>PriorityClass</PropertyName>
                <Label>PriorityClass</Label>
            </GroupBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Width>20</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>10</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>13</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>12</Width>
            </ViewSelectedBy>
            <GroupBy>
                <ScriptBlock>$_.StartTime.ToShortDateString()</ScriptBlock>
                <Label>StartTime.ToShortDateString()</Label>
            </GroupBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Width>20</Width>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>10</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>13</Width>
                        <Alignment>right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Width>12</Width>
            </ViewSelectedBy>
            <WideControl>
                <WideEntries>
                    <WideEntry>
                        <WideItem>
                            <PropertyName>ProcessName</PropertyName>
                        </WideItem>
                    </WideEntry>
                </WideEntries>
            </WideControl>
        </View>
        <View>
            <Name>DateTime</Name>
            <ViewSelectedBy>
                <TypeName>System.DateTime</TypeName>
            </ViewSelectedBy>
            <CustomControl>
                <CustomEntries>
                    <CustomEntry>
                        <CustomItem> <ExpressionBinding> <PropertyName>DateTime</PropertyName> </ExpressionBinding> </CustomItem> 

While the example code won’t emit the complete definition for sake of simplicity, it gives you a good view on what is happening behind the scenes: whenever a cmdlet returns objects of type System.Diagnostics.Process, PowerShell by default formats the data according to the exposed XML definition.

When you change the cmdlet name in the example above, you can see definitions of other types as well. However, for sake of simplicity, the example code only searches *.format.ps1xml files found in the PowerShell home directory and does not search in all of the module locations where additional formatting definitions may exist.

Note: This tip applies only to Windows PowerShell.


Twitter This Tip! ReTweet this Tip!