不确定为什么调用变量会改变输出



事情是这样的。我正在对一些代码进行故障排除,我注意到一个奇怪的行为。如果我使用以下代码:

$UpdateHistory = Get-WUHistory -last 1
$TodaysDate = (Get-Date)
$UpdateHistory.Date
$TodaysDate.DateTime

我得到了输出:

Sunday, April 17, 2022 10:01:13 AM
Thursday, April 21, 2022 11:23:00 AM

但是,如果我使用以下代码:

$UpdateHistory = Get-WUHistory -last 1
$TodaysDate = (Get-Date)
$UpdateHistory
$UpdateHistory.Date
$TodaysDate.DateTime

我得到这样的输出:

ComputerName Operationname  Result     Date                Title
------------ -------------  ------     ----                -----
RedactedComputerName Installation   Succeeded  4/17/2022 3:01:1... Windows Malicious Software Removal Tool x64 - v5.100 (KB890830)
Date        : 4/17/2022 12:00:00 AM
Day         : 17
DayOfWeek   : Sunday
DayOfYear   : 107
Hour        : 10
Kind        : Unspecified
Millisecond : 0
Minute      : 1
Month       : 4
Second      : 13
Ticks       : 637857864730000000
TimeOfDay   : 10:01:13
Year        : 2022
DateTime    : Sunday, April 17, 2022 10:01:13 AM
Thursday, April 21, 2022 11:23:56 AM

这到底是怎么回事?在第4行中使用$Updatehistory的原因只是为了查看条目列表,但它似乎从根本上改变了对象。这让我大吃一惊。

这个问题类似于为什么在一行中运行两个PowerShell命令时会改变输出格式?

长话短说:管道中的第一个对象输出可能会影响后续对象的呈现方式,特别是当它们不是同一类型时。

要获得一致的输出,要么在输出之前显式地转换它,要么将输出管道到format-table或format-list。

这不是改变对象,而是改变对象的显示方式:

smartiprefect的回答提供了一个伟大而简洁的总结;让我再深入一点:

具体来说,你会看到PowerShell的for-display输出格式化系统的以下行为:

  • 您正在向主机(显示)输出不同类型的多个对象。

  • 第一个输出对象$UpdateHistory包含一个数据类型,为其定义了显式格式化数据,该数据默认为视图(隐式Format-Table使用)。

  • 因为第二个输出对象是不同的类型([datetime]),第一个对象的格式化数据不能应用,PowerShell默认为Format-List格式化(就好像你已经调用了$UpdateHistory.Date | Format-List)

    • 警告
      • 如果第一个输出对象(非基本类型)有没有与其类型相关的格式化数据,如果对象有4个或更少(公共)属性,PowerShell默认为Format-Table格式化,如果对象有5个或更多,则默认为Format-List,显示所有这些属性。

      • 当选择Format-Table格式时,显示列根据第一个对象的属性被锁定在中。

      • 如果后续对象没有这些属性,它们可能在输出中看起来完全缺失:它们仍然存在,但不产生可见的输出。

      • 一个简单的例子,一个[pscustomobject]实例后面跟着一个[datetime]实例([pscustomobject]类型没有预定义的格式化数据与之关联):

        # !! Note how the Get-Date output appears to be missing.
        PS> [pscustomobject] @{ one = 1; two = 2; three = 3 }; Get-Date
        one two three
        --- --- -----
        1   2     3
        
      • 更多信息请看答案

  • 第三个输出对象是另一种类型[string]字符串总是输出与值相同的


解决方案是至少对您的第一个对象单独强制立即格式化输出到主机,这在Out-Host中是最简单的:

$UpdateHistory | Out-Host # Force instant formatted output to the host.
$UpdateHistory.Date
$TodaysDate.DateTime

但是,请注意,这绕过了成功输出流,因此以这种方式发送到显示的对象不再是脚本数据输出的一部分。

同样,如果你使用Format-*cmdlet而不是Out-Host,它是表示格式化指令的对象被发送到成功输出流;虽然它们在主机(显示)中按预期呈现,但它们作为数据是无用的。(但是,您可以格式化cmdlet与Out-Host结合使用;例:Get-ChildItem | Format-Table | Out-Host).

最新更新