Skip to main content
 首页 » 编程设计

powershell之为什么在一行中运行两个 PowerShell 命令时输出格式会发生变化

2025年05月04日154hnrainll

执行两个用分号分隔的 PowerShell 命令时,我得到了意想不到的结果。第二个命令的输出发生变化。如果我以相反的顺序运行它们,则看不到第二个命令输出。

在这里,我只是尝试获取时间戳和用户在 AD 中所属的组列表,作为单行。

如果我运行这一行,我会得到以下输出:

Get-ADPrincipalGroupMembership username | Select-Object name 
 
name 
---- 
Domain Users 
CL-Inventory-Group 
... 

但是,如果我运行以下命令,此行为会发生变化:
get-date; Get-ADPrincipalGroupMembership username | Select-Object name 
 
Wednesday, April 3, 2019 2:31:35 PM 
 
name : Domain Users 
 
 
name : CL-Inventory-Group 
 
 
... 

更奇怪的是,如果我反向运行,这意味着我在第一个命令之后说 get-date,则在列出组后永远不会显示日期戳。

我是否不正确地分隔命令?

请您参考如下方法:

tl;博士 :

提交多个 ; -separated 命令在提示符下(交互地)仍将其输出发送到单个管道(您可以将提交的每个命令行视为一个隐式脚本文件)。

简而言之:在你的情况下,第一个命令输出的自动显示格式也决定了第二个命令的显示格式,所以哪个命令最重要:

  • get-date; Get-ADPrincipalGroupMembership username | Select-Object name
  • 锁定在 Format-List 的隐式使用中对于 Get-Date 之后的所有输出,它解释了 Get-ADPrincipalGroupMembership ... 的每个属性本身的行输出命令。
  • If i run the reverse, meaning i say get-date after the first command, the date stamp never shows up after the groups are listed.


  • Select-Object [pscustomobject] 类型的输出实例,由于在这种情况下它们只有 1 个属性,因此锁定在表格显示中,即隐式使用 Format-Table ,将所选属性作为唯一列,即仅 Name这里。自 [datetime]类型输出 Get-Date没有 Name属性(property), Get-Date的输出实际上是不可见的。

  • 继续阅读背景信息和完整规则。

    PowerShell 的默认显示格式针对相同类型的对象进行了优化 ,因为这是典型的情况。

    如果管道包含多种类型,默认情况下产生的特定格式取决于 :
  • 管道中对象的顺序
  • 以及它们的默认格式化行为

  • 有关详细信息,请参阅下一节。

    您可以使用显式 Format-*调用控制格式 ;在你的情况下,你可以使用 Format-Table在你的第二个命令强制表格输出:
    Get-Date; Get-ADPrincipalGroupMembership username | Select name | Format-Table 
    

    警告 : 来自 Format-* 的输出cmdlet 是格式化指令而不是原始数据,这使得这个输出 不适合进一步的程序化处理 .

    PowerShell 如何格式化同一管道中不同类型的对象以供显示:

    如果没有明确的格式化命令( Format-TableFormat-List 、...)、 PowerShell 自动选择合适的显示格式 , 基于给定对象的类型:
  • 如果给定类型存在,PowerShell 使用预定义的格式化指令(参见 Get-Help about_Format.ps1xml )
  • 在他们不在的情况下:
  • 如果类型是原始类型(见下文):对象的 .ToString()表示是输出。
  • 否则:根据以下简单规则选择格式样式: 4 个或更少的属性? -> Format-Table ; 5个或更多? -> Format-List .

  • 注意:Primitive 在这里松散地用于指代:
  • 所有原始 CLR 类型 - 那些 .IsPrimitive 返回 $true ,即 [Boolean] , [Byte] , [SByte] , [Int16] , [UInt16] , [Int32] , [UInt32] , [Int64] , [UInt64] , [IntPtr] , [UIntPtr] , [Char] , [Double] , [Single]
  • 类型 [decimal] , [bigint] , [string][securestring]
  • 任何其他无属性类型。

  • 如果管道中的所有对象都属于同一类型,则上述定义适用于所有对象。

    相比之下, 如果管道中存在混合类型 ,以下逻辑适用:
  • 的任何实例原始类型总是打印相同的 ,即作为它们的单个值的表示(而不是作为具有属性的对象),通过调用它们的 .ToString() 获得方法;例如,123.0hi ;原始类型与管道中后续对象的格式无关。
  • 第一个非原始对象 在管线中:
  • 本身是根据其预定义的格式说明或上述默认规则(基于属性的数量)打印的。
  • 锁定格式样式 - 列表与表格 - 用于所有剩余的非原始对象 :
  • 如果对象本身隐式使用 Format-TableFormat-List ,所有剩余的非原始对象也将如此。
  • 如果对象隐式使用 Format-Custom (例如,在 Get-Date 的情况下,通过预定义的格式),它是 Format-List
  • 然后所有后续的非原始对象都使用锁定格式样式。
  • 警告 : 如果 Format-Table 已锁定,第一个非原始对象单独确定显示为表列的属性集 , 其中 如果后续对象没有这些属性,可能会导致后续对象看似消失 - 这些对象仍然在输出流中,但是,它们只是没有显示 - 参见 this answer用于演示。
  • 附带说明:从 PSv5 开始,隐式使用 Format-Table导致可能令人惊讶的异步行为;见 this answer .
  • 如果是Format-List被锁定,没有信息“丢失” ,因为每个对象的属性然后单独列出,在他们自己的行上。