您看到的是新 PowerShell v5 功能的结果。 Format-Table 现在收集输入 300 毫秒以找到更好的列宽。即使您明确指定-AutoSize:$false,它也会以这种方式工作。
当您在命令提示符下键入命令时,该命令会隐式通过管道传送到 Out-Default 命令的单个实例。 Out-Default 命令然后决定如何格式化对象并在 PowerShell 主机(控制台)上打印它们。因此,即使您没有在代码中直接使用Format-Table,也不意味着您的管道中没有Format-Table。 Out-Default 可以决定将对象格式化为表格并在内部使用Format-Table。
具有四个或更少属性且未在格式文件中为它们定义自定义格式的自定义对象被格式化为表格。通过将 Select-Object 与两个属性一起使用,您可以准确地生成该对象。
PowerShell 管道是单线程的。这意味着Format-Table 不能在经过 300 毫秒间隔后才输出所有收集的对象。 Format-Table 必须等到您将下一个项目通过管道传递给它(调用进程块)或报告管道结束(调用结束块)。
PS> Get-NetAdapter | Select-Object Name,Status
>>> Pause
>>> [PSCustomObject]@{Name='Some long name';Status='Some long status'} #1
>>> Pause
>>> [PSCustomObject]@{Name='Even longer name';Status='Even longer status'}
>>> Pause
Press Enter to continue...:
Name Status
---- ------
Ethernet Up
Some long name Some long status
Press Enter to continue...:
Even longer... Even longer s...
Press Enter to continue...:
PS>
隐式Format-Table 在第一个Pause 之前不打印任何内容(严格地说它打印空行),因为它仍在等待更多输入对象(尚未经过300 毫秒)来决定列宽。当第一个对象 (#1) 在 300 毫秒间隔后出现时(假设您按 Enter 不快),然后Format-Table 决定列宽并打印所有收集的对象。任何其他对象都将立即打印,但它们不再影响列宽。如果列的值太大,它将被截断。
PS> Get-NetAdapter | Select-Object Name,Status | Format-Table
>>> Pause
Name Status
---- ------
Ethernet Up
Press Enter to continue...:
PS>
使用此代码,显式Format-Table 的结束块将在Pause 之前执行。在结束块Format-Table 知道它已经获得了所有输入,因此它可以决定列宽并立即输出所有收集的对象。隐式Out-Default 看到来自Format-Table 输出的格式化对象,Out-Default 知道它们不需要任何额外的格式化并立即在主机(控制台)上打印它们。所以整个表格在Pause 被调用之前就被打印出来了。
注意表格结束标记(两个空行)的位置差异。在第一个示例中,它放在最后一个 Pause 之后。这是因为隐式 Format-Table 仍然处于活动状态并且仍在等待,所以您将附加对象传递给它。仅当您的命令完全完成时Format-Table 确认输入结束和表格标记的输出结束。在第二个示例中,显式 Format-Table 在 Pause 之前完成,因此整个表(包括表尾标记)在 Pause 命令之前打印。
在以前版本的 PowerShell 中也可以注意到表格结束标记的位置差异。