Powershell - 获取显示在控制台中的对象属性

Powershell - Get object properties displayed in console

重点是用控制台中显示的 Powershell 对象的 属性 名称填充变量。 意思是,如果我 运行 Get-Process,我只想在控制台中返回八个对象的属性,即 'Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName'.

Get-Member 命令在这里没有帮助。

有人可以帮我吗?

谢谢大家!

获取 名称 - 可能是也可能不是 属性 名称 - table 视图 为给定的 .NET 类型呈现 如果它有 predefined formatting data(包括一个 table 视图)与之关联:

  • 注意:
    • 以下是一个正确但重要且有限的解决方案,它使用找到的 first table-view 定义从格式化数据派生列名。它还具有概念背景信息。
      • 参见底部 quick-and-dirty 解决方案仅获取列名,它使用文本解析直接从给定命令的格式化输出中提取列名。
    • 中间部分建立在第一部分的基础上,提取了一个属性名称列表和反映列定义的计算属性,可以是与 Select-Object 一起使用,以创建具有与格式化数据生成的值相同的属性的自定义对象。
# 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, with a calculated column value or renamed property
            else           { $rows.Columns[$i].DisplayEntry.Value } # Property name, with its value as the column value.
            ++$i
          }
        }

警告:以上限制输出到 first table-view 找到的定义 - 这可能适用于也可能不适用于给定的命令。默认情况下 选择哪个定义 可能受与 select 基于运行时条件的定义相关的标准约束,包括 select 特定输入类型,假设格式化数据的单个实例可以涵盖 多种 类型。 另请注意,视图可能涉及 grouping(例如,如您在 Get-ChildItem 的格式化输出中所见),并且上述命令未涵盖分组标准。
请注意,即使对于单一类型 也可以定义多个视图 ,并且为了使用 non-default 一个,您必须通过 Format-Table-View 参数,假设您知道名称,[1] 例如Get-Process | Format-Table -View StartTime).

  • 另请参阅:
    • 了解如何检查格式化数据 完整
      • 您可以选择将 Get-FormatData 输出通过管道传输到 Export-FormatData,以便将格式化数据导出到 XML 文件,其缺点是难以阅读,但优点是匹配用于 authoring 格式化数据的 XML 模式 - 参见下一点 - 而用于表示格式化数据的 in-memory 类型部分使用 属性 名称与基础 XML 元素不匹配。
    • 至于编写 格式化数据,从 PowerShell 7.2.2 开始需要 XML 文件 (*.Format.ps1xml):

注:

  • 只有在 Windows PowerShell 中才需要将 -PowerShellVersion $PSVersionTable.PSVersionGet-FormatData 一起使用,以解决某些类型的问题PowerShell (Core) 7.1+

    中不再存在的错误
  • 虽然名称通常对应于属性 正在格式化的类型实例的名称,但情况并非总是如此,例如 [System.Diagnostics.Process] instances output by Get-Process.

    • 一般警告,正如zett42所指出的那样,类型的显示格式不属于public 关于中断更改的合同,因此允许格式定义随时间更改。
  • 如果给定类型没有预定义格式数据与之关联(在这种情况下Get-FormatData是安静的no-op) :

    • 其(public)实例属性的名称用作列 名字。

    • 如果有 4 个或更少的属性,默认情况下您只会获得 table 视图,但是您可以通过默认应用 Format-Table (With 5 or more properties, Format-List 来明确请求它。

    • 要获取给定对象的所有 (public) 个实例属性的名称,请使用 intrinsic .psobject property,这是一个丰富的反射源;例如:

      • (Get-Process | Select-Object -First 1).psobject.Properties.Name

要创建 属性 名称和 calculated properties 的列表,可与 Select-Object 一起使用,反映 formatting-data 的列定义:

# Determine the .NET type of interest.
$type = (Get-Process)[0].GetType()

# Get an array of property names / calculated properties from the
# formatting data, for later use with Select-Object
$props = 
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) { # Explicit label, with a calculated column value or renamed property
              @{ 
                Name = $colLabel
                Expression = if ('ScriptBlock' -eq $rows.Columns[$i].DisplayEntry.ValueType) {
                               [scriptblock]::Create($rows.Columns[$i].DisplayEntry.Value) 
                             } else { 
                               $rows.Columns[$i].DisplayEntry.Value
                             } 
              } 
            }
            else { # Property name, with its value as the column value.
              $rows.Columns[$i].DisplayEntry.Value
            }
            ++$i
          }
        }

# Sample call
Get-Process | Select-Object -Property $props | Format-Table | more
  • 示例调用产生与单独 Get-Process 相似的输出,因为它使用列定义作为(计算的)属性 - 尽管使用列宽和对齐等格式化属性的默认值.

  • 注意显式使用 Format-Table 以确保 tabular 输出;没有它 - 假定由 Select-Object 创建的 [pscustomobject] 实例没有与其关联的格式数据 - list 格式(隐含的 Format-List)将会产生。

  • 正如 Mathias 指出的那样,计算的 属性将是 strin 类型甚至基于 numeric 属性的列,因为它们在格式化数据中的目的是创建格式化字符串表示。


Quick-and-dirty 仅获取 列名称的解决方案:

以下使用 Out-String -Stream in conjunction with Select-String 从给定命令的格式化输出中提取列名,这依赖于两个假设:

  • 列名没有嵌入空格
  • 命令实际上默认产生table格式的输出;但是,如果需要,您可以在 Out-String 之前插入 Format-Table 调用。
Get-Process | Out-String -Stream | Select-String -List '^\s*--+' -Context 1, 0 |
  ForEach-Object { -split $_.Context.PreContext[0] }

输出:

NPM(K)
PM(M)
WS(M)
CPU(s)
Id
SI
ProcessName

注意:在 Windows PowerShell 中,另一个 属性 显示为第一个:Handles.


[1] 虽然 tab-completion 确实提供了视图名称,但从 PowerShell 7.2.2 开始,它们似乎与实际可用的名称不同步。要查看后者,请使用 dummy 名称引发错误,错误消息将列出可用的;例如Get-Process | Format-Table -View NoSuch 在生成的错误消息中列出了以下可用视图:process, Priority, StartTime