3 回答
TA贡献1797条经验 获得超6个赞
您看到的是新PowerShell v5功能的后果。Format-Table现在收集输入300毫秒,以找到更好的列宽。即使您明确指定,它也会以这种方式工作-AutoSize:$false。
在命令提示符下键入command时,该命令隐式地通过管道传递给单个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的早期版本中注意到。
TA贡献1864条经验 获得超2个赞
Format-Table
与此无关我只是在PowerSell V 4.0和PowerShel V5.0中尝试以下内容并且可以重现该问题:
Get-Process |Select-Object -Property name ; pause
转弯是:
Get-Process |Select-Object -Property Name |%{Write-host $_.name};pause
这里再次暂停运行:
Get-Process |%{$_.name | Set-Content 'c:\temp\test.txt';$_} |Select-Object -Property Name ;pause
但不是在这里
Get-Process |%{$_.name | Set-Content 'c:\temp\test.txt';Start-Sleep -Milliseconds 1;$_} |Select-Object-Property Name ;pause
对我来说,在PowerShell V5.0中,一切都像在流水线操作的指令中不需要主机一样,然后这些指令以异步方式运行。
TA贡献1777条经验 获得超10个赞
一切都隐含地用管道输送Out-Default
,所以你的第一个代码相当于.{Get-Process |Select-Object -Property name ; pause}|Out-Default
。并Out-Default
决定使用Format-Table
格式化输出。所以事实上你有.{Get-Process |Select-Object -Property name ; pause}|Format-Table
。如果更改Format-Table
为Format-List
或明确设置列宽Format-Table @{e='Name';w=50}
,则pause
在输出后将调用。如果在每个输出对象上添加时序,那么您将看到,在300毫秒间隔后开始输出。
添加回答
举报