Use Powershell script to display just alias name c

2020-04-01 07:37发布

问题:

I'm fairly new to powershell scripting after years of unix/linux scripting and I'm still trying to get the handle of object output. I am trying to run the Get-Alias command to return just the column "Name." When I try to select just the column "name" I either get the whole get-alias output, or errors. The script/ command line I am trying to use is: get-alias | format-table

When I add select-object logic, it either cuts off the name of the alias and leaves off the command name or the select-object logic is just ignored. I'm sure the solution is simple. Thanks

回答1:

tl;dr:

PS> Get-Alias | Select-Object -ExpandProperty DisplayName

? -> Where-Object                                                                                              
cd -> Set-Location 
...

That is, the true property name underlying the Name display column is DisplayName.


PowerShell's default output formatting sometimes uses column names that differ from or the underlying objects' property names (which is the case here) and/or use values that are calculated.

What shows as column Name by default is actually the underlying objects' .DisplayName property, whereas the true .Name property contains just the alias' own name.

You can inspect the members (properties and methods) of an object's type via Get-Member or, to see both the property (but not method) names and their concrete values for a given object, pipe to Format-List *:

PS> Get-Alias | Select-Object -First 1 | Format-List *

HelpUri             : https://go.microsoft.com/fwlink/?LinkID=113423
ResolvedCommandName : Where-Object
DisplayName         : ? -> Where-Object
ReferencedCommand   : Where-Object
ResolvedCommand     : Where-Object
Definition          : Where-Object
Options             : ReadOnly, AllScope
Description         : 
OutputType          : {}
Name                : ?
CommandType         : Alias
Source              : 
Version             : 
Visibility          : Public
ModuleName          : 
Module              : 
RemotingCapability  : None
Parameters          : {[InputObject, System.Management.Automation.ParameterMetadata], [FilterScript, System.Management.Automation.ParameterMetadata], [Property, 
                      System.Management.Automation.ParameterMetadata], [Value, System.Management.Automation.ParameterMetadata]...}
ParameterSets       : 

Optional reading: How to inspect a given type's formatting data:

For background information, see Get-Help about_Format.ps1xml.

Get-Alias outputs [System.Management.Automation.AliasInfo] instances (as Get-Member will tell you).

Using the Get-FormatData cmdlet you can inspect a type's formatting data:

Caveat: Not all formatting data in effect is by default reported by Get-FormatData for backward-compatibility reasons - see this GitHub issue; notable omissions are [System.IO.FileInfo] and [System.IO.DirectoryInfo], as returned by Get-ChildItem / Get-Item ; in short, to see all formatting data in effect for the PowerShell version at hand, use:

Get-FormatData -PowerShellVersion $PSVersionTable.PSVersion [...]

Somewhat ironically, there is no custom formatting data defined for the System.Management.Automation.ExtendedTypeDefinition instances that Get-Format outputs, and the default formatting isn't helpful.

Currently, the simplest way to inspect formatting data is to pipe to the Format-Custom cmdlet, which provides an informal, human-readable representation of the internal structure of objects:

# Best to send this to a file and open that file in a text editor for perusal.
$prev, $FormatEnumerationLimit = $FormatEnumerationLimit, [int]::MaxValue
Get-FormatData System.Management.Automation.AliasInfo | Format-Custom -Depth 10
$FormatEnumerationLimit = $prev

Note:

  • $FormatEnumerationLimit is temporarily set to the highest possible value to ensure that all column / property definitions are shown in the output (by default, only up to 4 would be shown, and omitted ones would be indicated with ... (Windows PowerShell, 3 chars.) / (PowerShell Core, 1 char.).

  • -Depth 10 ensures that the internal structure of the output objects is fully represented; by default, only up to 5 levels would be.

The output will look vaguely like JSON, and is suited to visual inspection only, not programmatic processing.

You'll see one or more of the following blocks:

class ExtendedTypeDefinition
{
  TypeNames = 
    [
      <typeName>
    ]

  FormatViewDefinition = 
    [
      class FormatViewDefinition
      {
        Name = <formatName>
        Control = 
          class <viewType>Control
        ...
      }
      class FormatViewDefinition
      {
        Name = <formatName>
        Control = 
          class <viewType>Control
        ...
      }
}
  • <typeName> is the full type name to which the format applies (e.g., System.Management.Automation.AliasInfo)

  • <formatName> is an internally used, non-standardized name for the format-definition at hand

  • <viewType>Control is one of the following classes, defining the views for use with the corresponding Format-Table,Format-List, Format-Wide, and Format-Custom cmdlets: TableControl, ListControl, WideControl, CustomControl, all derived from the System.Management.Automation.PSControl base class.

Note that the output may contain duplicate information, as it does in the case of System.Management.Automation.AliasInfo (because the formatting information is repeated for all other command types that share the same formatting), but it is sufficient to examine the first class <viewType>Control instance of interest.

Specifically, here's an excerpt from the first class TableControl block:

class TableControl   # Defines the format for Format-Table
{
  Headers =   # The table headers (column names and column properties)
      ...
      class TableControlColumnHeader # The "Name" column *header*
      {
        Label = Name
        Alignment = Undefined
        Width = 50
      }
      ...
    ]

  Rows =  # The table rows (underlying or calculated property values)
    [
      class TableControlRow
      {
        Columns = 
          [
            ...
            class TableControlColumn  # The "Name" column *value*
            {
              Alignment = Undefined
              DisplayEntry = 
                class DisplayEntry
                {
                  ValueType = ScriptBlock  #  A *calculated* property 
                  Value = 
                                                  if ($_.CommandType -eq "Alias")
                                                  {
                                                    $_.DisplayName
                                                  }
                                                  else
                                                  {
                                                    $_.Name
                                                  }

                }
              FormatString = 
            }
            ...
    ]
    ...

Note that the header and column-value definitions are matched positionally; e.g., the 2nd TableControlColumn instance defines the value for the 2nd TableControlColumnHeader instance.

The above explains why, even though the column is entitled "Name", it is an alias' .DisplayName property that is displayed, whereas all the other command types are represented by their .Name property, by way of the embedded script block (the piece of PowerShell code in which $_ represents the input object at hand).

Presumably, the decision to show the .DisplayName for aliases was made to provide more helpful information by default, but the discrepancy between the column name and underlying property name can certainly lead to confusion.

Note that there is also a dedicated table view for type [System.Management.Automation.AliasInfo] that (a) defines only 2 columns, and (b) calls the .DisplayProperty column values by their true name.
However, as of the PowerShell versions listed above, this view is preempted by the multi-type definition discussed above and effectively ignored.