SoFunction
Updated on 2025-03-10

Windows Powershell Extended Type System

One of the most attractive features of Powershell is its ability to convert any object into text. We have used to convert object properties into text in different layouts and output it. What is even more surprising is that Powershell will output the most important information that best represents the essence of this object. An object has many properties, why does it output those properties alone?
If using:

Copy the codeThe code is as follows:

Dir | Format-Table * -wrap
PSP PSP PSC PSD PSP PSI Bas Mod Nam Par Exi Roo Ful Ext Cre Cre Las La La La At
ath are hil riv rov sCo eNa e   e   ent sts t   lNa ens ati ati tAc st st st tr
    ntP dNa e   ide nta me                      me  ion onT onT ces Ac Wr Wr ib
    ath me      r   ine                                 ime ime sTi ce it it ut
                      r                                     Utc me  ss eT eT es
                                                                    Ti im im
                                                                    me e  eU
                                                                    Ut    tc
                                                                    c
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- -- -- -- --
Mic Mic ABC C   Mic Tru ABC d-- ABC Pow Tru C: C:     201 201 201 20 20 20 Di
ros ros         ros   e     --      ers   e     Pow     1/1 1/1 1/1 11 11 11 re
oft oft         oft                 hel         ers     2/1 2/1 2/1 /1 /1 /1 ct
.Po .Po         .Po                 l           hel     9 1 9 9 9 1 2/ 2/ 2/ or
wer wer         wer                             lA     7:0 :05 7:0 19 19 19  y
She She         She                             BC      5:5 :55 5:5  9  1  9
ll. ll.         ll.                                     5       5   :0 7: :0
Cor Cor         Cor                                                 5: 05 5:
eF eF         eF                                                 55 :5 55
ile ile         ile                                                    5
Sys Sys         Sys
tem tem         tem
::C ::C
 
owe owe
rsh rsh
ell ell
AB
C

Powershell will output each attribute to the maximum extent, but such output is basically meaningless and is not conducive to user reading. So what exactly makes Powershell only display this property but not that property by default? It is the "extended type system" Extended Type System (ETS), which will macro-control the mechanism for converting objects into text in the pipeline.
ETS consists of two parts, one controls the layout of the object and the other controls the properties of the object. Today, we mainly care about the first part.

Text conversion irreversible

After converting the object result into text in the pipeline, the text cannot be converted into objects anymore because ETS cannot process text.
If the directory list is converted into a String through ConvertTo-String, the commands such as Format-Table and Format-List will be invalid.

Copy the codeThe code is as follows:

PS C:Powershell> $text= dir | Out-String
PS C:Powershell> $text

Table of Contents: C:Powershell

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2011/12/19     17:05            ABC
d----        2011/12/19     17:06            ABD
d----        2011/12/19     17:06            ABE

PS C:Powershell> $text | Format-Table

Table of Contents: C:Powershell

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2011/12/19     17:05            ABC
d----        2011/12/19     17:06            ABD
d----        2011/12/19     17:06            ABE

PS C:Powershell> $text | Format-List

Table of Contents: C:Powershell

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2011/12/19     17:05            ABC
d----        2011/12/19     17:06            ABD
d----        2011/12/19     17:06            ABE

Select properties

ETS also won't work if a command like Format-Table is used when displaying the object results, because Format-Table converts the value of each property into text. So sometimes, it is best to specify the properties you display clearly and do not hand over the power of life and death to ETS.

Copy the codeThe code is as follows:

PS C:Powershell> dir | Format-Table Mode,FullName

Mode  FullName
----  --------
d---- C:PowershellABC
d---- C:PowershellABD
d---- C:PowershellABE
d---- C:Powershellmyscript
-a--- C:
-a--- C:
-a--- C:
-a--- C:
-a--- C:Powershellalias

Known object formatting

If a formatted command is used, but no specific attribute is specified (such as: dir | Format-Table). ETS will make its first move, and it will determine which objects should be displayed and which attributes should be automatically selected. Before doing these tasks, ETS should first figure out that those objects can be converted into text.

Copy the codeThe code is as follows:

PS C:Powershell> (dir)[0].GetType().FullName

Dir returns an object and contains the objects and child objects in this object. In this way, ETS can check its own internal records and convert the object into text through the internal records configuration. These internal records are XML files with the extension ".ps1xml"

Copy the codeThe code is as follows:

PS C:Powershell> dir $PSHOME*format.ps1xml

Directory: C: WindowsSystem32WindowsPowerShellv1.0

Mode         LastWriteTime Length Name
----         ------------- ------ ----
-a---  2009/6/11      5:24  27338 .ps1xml
-a---  2009/6/11      5:24  27106 .ps1xml
-a---  2009/6/11      5:24  72654 .ps1xml
-a---  2009/6/11      5:24  24857 .ps1xml
-a---  2009/6/11      5:24 257847 .ps1xml
-a---  2009/6/11      5:24  89703 .ps1xml
-a---  2009/6/11      5:24  18612 .ps1xml
-a---  2009/6/11      5:24  20120 .ps1xml
-a---  2009/6/11      5:24  24498 .ps1xml

Each object is defined in detail in these XML files, including those object properties that support conversion into text, and those objects should be displayed in a list or table by default.
One thing I said before is that ETS is not supported for the mixed command "Get-Process ; dir" above one line. The best way to avoid it is to specify the layout explicitly for each command.

PS C:Powershell> Get-Process | Format-Table ; dir | Format-Table

Unknown object formatting

Objects defined in ps1xml are known objects. How should those unknown objects ETS be handled? For unknown objects, ETS follows a rule:
If the object has less than 5 properties, the table will be displayed, otherwise the list will be displayed.
The following example creates an object and adds attributes to the object one by one.

Copy the codeThe code is as follows:

PS C:Powershell> $obj=New-Object PSObject
PS C:Powershell> Add-Member -Name A -Value 1 -InputObject $obj
MemberType: PS C:Powershell>
PS C:Powershell> Add-Member -MemberType NoteProperty -Name "A" -Value "1" -InputObject $obj
PS C:Powershell> $obj

A
-
1

PS C:Powershell> Add-Member -MemberType NoteProperty -Name "B" -Value "2" -InputObject $obj
PS C:Powershell> Add-Member -MemberType NoteProperty -Name "C" -Value "3" -InputObject $obj
PS C:Powershell> Add-Member -MemberType NoteProperty -Name "D" -Value "4" -InputObject $obj
PS C:Powershell> $obj

A B C D
- - - -
1 2 3 4

PS C:Powershell> Add-Member -MemberType NoteProperty -Name "E" -Value "5" -InputObject $obj
PS C:Powershell> $obj

A : 1
B : 2
C : 3
D : 4
E : 5

Emergency mode

If ETS finds a critical state from the output, it will automatically switch to the list display. For example, "Get-Process; Dir", ETS is outputting Process objects in a table form, but suddenly encountering a FileInfo object, it will directly switch to list mode and output other types of objects.

Hide columns

If you encounter an unknown object, ETS will try to find clues from the first result output from the pipeline, which may lead to a strange phenomenon. ETS will judge attributes based on the first result of an unknown object, but the attributes of the first result will not always be output. When an object containing more attributes may be encountered, the currently selected attribute information may be suppressed.
The following example demonstrates that information will be suppressed. Get-Process returns all running processes, and then sorts them through StartTime, and outputs the name and opening time of each process:

Copy the codeThe code is as follows:

PS C:Windowssystem32> Get-Process | Sort-Object StartTime | Select-Object Name
,StartTime
Sort-Object: An exception occurred while getting "StartTime": "Access denied."
Location Line: 1 Character: 26
+ Get-Process | Sort-Object <<<< StartTime | Select-Object Name,StartTime
+ CategoryInfo : InvalidResult: ( (audi
odg):PSObject) [Sort-Object], GetValueInvocationException
+ FullyQualifiedErrorId : ExpressionEvaluation,

When executing the above command line, you will receive many error messages. These error messages do not come from commands, but may be that some system processes deny access because the current console does not have administrator rights. Some of the output processes may have only process name (Name) and no start time (StartTime), and the start time is suppressed.
Using Select-Object will delete some properties of the object, but the properties of the object itself cannot be deleted, so ETS will regenerate an object in the pipeline with the type:.

Copy the codeThe code is as follows:

PS C:Powershell> Get-Process | foreach {$_.gettype().fullname} | select -f 1

PS C:Powershell> (Get-Process | foreach {$_.gettype().fullname} | select -f 1 Name ).getType().fullname

Because PSCustomObject is not recorded in the ETS configuration, all properties will be output. The pipeline results were previously arranged according to StartTime ascending order, so the previous process did not have StartTime due to permission issues.

Expand ETS

Type objects included in the ETS configuration are converted into text in the best way. However, the performance of unknown objects is imperfect, and imperfect performance does not mean that there is no way to go. Fortunately, ETS can be expanded to allow ETS to handle new objects in the best way.
The first step in expanding ETS is to determine the type of object to be expanded. We may often obtain WMI services through Get-WmiObject. But if you don't like Powershell's default output, you can expand ETS.

Copy the codeThe code is as follows:

PS C:Powershell> Get-WmiObject Win32_Processor

__GENUS                     : 2
__CLASS                     : Win32_Processor
__SUPERCLASS                : CIM_Processor
__DYNASTY                   : CIM_ManagedSystemElement
__RELPATH                   : Win32_Processor.DeviceID="CPU0"
__PROPERTY_COUNT            : 48
__DERIVATION                : {CIM_Processor, CIM_LogicalDevice, CIM_LogicalEle

First determine the type of object that the command returns the result

Copy the codeThe code is as follows:

PS C:Powershell> $object = Get-WmiObject Win32_Processor | Select-Object -first 1
PS C:Powershell> $().FullName

The target type is found:
Next create a configuration file:

Copy the codeThe code is as follows:

<configuration>
<viewdefinitions>
<view>
<name>CustomView</name>
<viewselectedby>
<typename></typename>
</viewselectedby>
<tablecontrol>
<tableheaders>
<tablecolumnheader>
<label>Name</label>
<width>12</width>
</tablecolumnheader>
<tablecolumnheader>
<label>Description</label>
<width>30</width>
</tablecolumnheader>
<tablecolumnheader>
<label>ID</label>
</tablecolumnheader>
</tableheaders>
<tablerowentries>
<tablerowentry>
<tablecolumnitems>
<tablecolumnitem>
<propertyname>DeviceID</propertyname>
</tablecolumnitem>
<tablecolumnitem>
<propertyname>Description</propertyname>
</tablecolumnitem>
<tablecolumnitem>
<propertyname>ProcessorID</propertyname>
</tablecolumnitem>
</tablecolumnitems>
</tablerowentry>
</tablerowentries>
</tablecontrol>
</view>
</viewdefinitions>
</configuration>

Save the file as Win32_Processor.format.ps1xml, then use the command Update-FormatData to load it into ETS, which will take effect immediately.

Copy the codeThe code is as follows:

PS C:Powershell> Update-FormatData .Win32_Processor.format.ps1xml
PS C:Powershell> Get-WmiObject win32_processor

Name         Description                    ID
----         -----------                    --
CPU0         x64 Family 6 Model 15 Stepp... BFEBFBFF000006FD

However, such a definition may have a disadvantage. When we obtain other WMI objects, it will also be displayed according to the rules we define.

Copy the codeThe code is as follows:

PS C:Powershell> Get-WmiObject Win32_Share

Name         Description                    ID
----         -----------                    --
             Remote Admin
             Default share
             HP LaserJet P2050 Series PCL6
             Remote IPC
             Printer Drivers

The above situation occurs because all objects of WMI will be returned as type. Therefore, ETS did not make any mistakes, and the culprit was the special type of WMI. Therefore, when expanding ETS, you must refine a specific type. In fact, the WMI object has a PSTypeNames property, through which you can find more specific types.

Copy the codeThe code is as follows:

PS C:Powershell> $object = Get-WmiObject Win32_Processor | Select-Object -first1
PS C:Powershell> $
#rootcimv2Win32_Processor





The inheritance hierarchy of WMI object types is shown above. Therefore, the object type we want to extend in our needs should be: #rootcimv2Win32_Processor

Therefore, the configuration file should be modified and the update should be reloaded. There will be an exception when updating
Update-FormatData: An error occurred while loading the format data file:
, C:PowershellWin32_Processor.format.ps1xml: The file was skipped,
Because the file has appeared in "".

The exception can be ignored and then retested.

Copy the codeThe code is as follows:

PS C:Powershell> Get-WmiObject win32_Processor

Name         Description                    ID
----         -----------                    --
CPU0         x64 Family 6 Model 15 Stepp... BFEBFBFF000006FD

PS C:Powershell> Get-WmiObject win32_share

Name                       Path                       Description
----                       ----                       -----------
ADMIN$                C:Windows          Remote Admin
C$                         C:                        Default share

In this way, the ETS expansion is only valid for Win32_Processor. No other parent type objects are affected.