The point is to populate a variable with a Powershell object's property name displayed in a console.
Meaning, if I run Get-Process
, I only want the eight object's properties returned in the console which are 'Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName'.
Get-Member
command is not helpful here.
Can anyone help me with that?
Thank you all!
CodePudding user response:
To get the column names - which may or may not be property names - of the table view that is presented for a given .NET type if it has predefined formatting data (that includes a table view) associated with it:
- Note:
- The following is a proper, but nontrivial solution that derives the column names from the formatting data, using the first table-view definition found. It also has conceptual background information.
- See the bottom section for a quick-and-dirty solution, which uses text parsing to extract the column names directly from a given command's formatted output.
# Determine the .NET type of interest.
$type = (Get-Process)[0].GetType()
# Extract the names of the column headers from the *first* table-view definition.
Get-FormatData $type -PowerShellVersion $PSVersionTable.PSVersion |
ForEach-Object FormatViewDefinition |
Where-Object Control -is [System.Management.Automation.TableControl] |
Select-Object -First 1 |
ForEach-Object {
$i = 0
$rows = $_.Control.Rows
foreach ($colLabel in $_.Control.Headers.Label) {
if ($colLabel) { $colLabel } # Explicit label, typically with a calculated column value
else { $rows.Columns[$i].DisplayEntry.Value } # Property name, with its value as the column value.
$i
}
}
Caveat: The above limits output to the first table-view definition found - which may or may not apply to a given command. Which definition is chosen by default is potentially governed by criteria associated with the definitions that select based on runtime conditions, including selecting by specific input type, given that a single instance of formatting data can cover multiple types.
Also note that views may involve grouping (as you see in Get-ChildItem
's formatted output, for instance), and the grouping criterion isn't covered by the command above.
Note that even for a single type multiple views may be defined, and in order to use a non-default one you must request it explicitly, via Format-Table
's -View
parameter, assuming you know the name,[1] e.g. Get-Process | Format-Table -View StartTime)
.
- See also:
- This answer for how to inspect formatting data in full.
- You can alternatively pipe
Get-FormatData
output toExport-FormatData
in order to export formatting data to an XML file, which has the disadvantage of being hard to read, but has the advantage of matching the XML schema used for authoring formatting data - see next point - whereas the in-memory types used to represent formatting data partially use property names that don't match the underlying XML elements.
- You can alternatively pipe
- As for authoring formatting data, which as of PowerShell 7.2.2 requires XML files (
*.Format.ps1xml
):- See this answer for an example of how to define your own table view.
- Formatting File Overview and the Format Schema XML Reference
- This answer for how to inspect formatting data in full.
Note:
Using
-PowerShellVersion $PSVersionTable.PSVersion
withGet-FormatData
is only needed in Windows PowerShell, for certain types, to work around a bug that is no longer present in PowerShell (Core) 7.1While column names typically correspond to the property names of the type instances being formatted, that isn't always the case, such as with the
[System.Diagnostics.Process]
instances output byGet-Process
.- A general caveat, as zett42 notes, is that display formatting of types isn't part of the public contract regarding breaking changes, so formatting definitions are allowed to change over time.
If a given type has no predefined formatting data associated with it (in which case
Get-FormatData
is a quiet no-op):The names of its (public) instance properties are used as column names.
You only get a table view by default if there are 4 or fewer properties but you can request it explicitly with
Format-Table
(With 5 or more properties,Format-List
is applied by default).To get the names of all (public) instance properties of a given object, use the intrinsic
.psobject
property, which is a rich source of reflection; e.g.:(Get-Process | Select-Object -First 1).psobject.Properties.Name
Quick-and-dirty solution:
The following uses Out-String
-Stream
in conjunction with Select-String
to extract the column names from a given command's formatted output, which relies on two assumptions:
- The column names have no embedded spaces
- The command actually produces table-formatted output by default; however, you can insert a
Format-Table
call beforeOut-String
, if desired.
Get-Process | Out-String -Stream | Select-String -List '^\s*-- ' -Context 1, 0 |
ForEach-Object { -split $_.Context.PreContext[0] }
Output:
NPM(K)
PM(M)
WS(M)
CPU(s)
Id
SI
ProcessName
[1] While tab-completion does offer view names, they appear to be out of sync with the actually available ones, as of PowerShell 7.2.2. To see the latter, provoke an error with a dummy name, and the error message will list the available ones; e.g. Get-Process | Format-Table -View NoSuch
lists the following available views in the resulting error message: process, Priority, StartTime