tl;dr:
Submitting multiple ;
-separated commands at the prompt (interactively) still sends their output to a single pipeline (you can think of each command line submitted as an implicit script file).
In short: in your case, the first command output's automatic display formatting also determined the display formatting for the 2nd command, so which command comes first matters:
Read on for background information and the complete rules.
PowerShell's default display formatting is optimized for objects of the same type, as that is the typical case.
If a pipeline contains a mix of types, the specific formatting that results by default depends on:
- the order of objects in the pipeline
- and their default formatting behavior
See the next section for details.
You can use explicit Format-*
calls to control the formatting; in your case, you can use Format-Table
on your 2nd command to force tabular output:
Get-Date; Get-ADPrincipalGroupMembership username | Select name | Format-Table
Caveat: The output from Format-*
cmdlets are formatting instructions rather than the original data, which makes this output unsuitable for further programmatic processing.
How PowerShell formats objects of different types in the same pipeline for display:
In the absence of explicit formatting commands (Format-Table
, Format-List
, ...), PowerShell automatically chooses a suitable display format, based on a given object's type:
- If present for a given type, PowerShell uses predefined formatting instructions (see
Get-Help about_Format.ps1xml
)
- In their absence:
- If the type is a primitive type (see below): the object's
.ToString()
representation is output.
- Otherwise: the format style is chosen based on the following simple rules: 4 or fewer properties? ->
Format-Table
; 5 or more? -> Format-List
.
Note: Primitive is used loosely here to refer to:
- all primitive CLR types - those for which
.IsPrimitive
returns $true
, namely
[Boolean]
, [Byte]
, [SByte]
, [Int16]
, [UInt16]
, [Int32]
, [UInt32]
, [Int64]
, [UInt64]
, [IntPtr]
, [UIntPtr]
, [Char]
, [Double]
, [Single]
- types
[decimal]
, [bigint]
, [string]
and [securestring]
- any other property-less types.
If all objects in a pipeline are of the same type, the above by definition applies to all of them.
By contrast, if there is a mix of types in the pipeline, the following logic applies:
Any instances of primitive types always print the same, namely as a representation of the single value that they are (not an as an object with properties), obtained via a call to their .ToString()
method; e.g., 12
or 3.0
or hi
; primitive types have no bearing on the formatting of subsequent objects in the pipeline.
The first non-primitive object in the pipeline:
is itself printed based on either its predefined formatting instructions or the default rules stated above (based on the number of properties).
locks in the format style - list vs. table - for all remaining non-primitive objects:
- If the object itself implicitly uses
Format-Table
or Format-List
, so will all remaining non-primitive objects.
- If the object implicitly uses
Format-Custom
(e.g, in the case of Get-Date
, via predefined formatting), it is Format-List
that is locked in.
All subsequent non-primitive objects then use the locked-in format style.
Caveat: If Format-Table
is locked in, the first non-primitive object alone determines the set of properties displayed as table columns, which can cause subsequent objects to seemingly disappear if they don't have these properties - such objects are still in the output stream, however, they're just not displayed - see this answer for a demonstration.
- On a side note: Since PSv5, implicit use of
Format-Table
results in asynchronous behavior that may be surprising; see this answer.
If it is Format-List
that is locked in, no information is "lost", as each object's properties are then listed individually, on their own lines.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…