为了账号安全,请及时绑定邮箱和手机立即绑定

Select-Object后无法暂停或休眠

Select-Object后无法暂停或休眠

Select-Object后无法暂停或休眠在某些情况下,如果我尝试在Select-Object命令后暂停或休眠,则在命令之前发生暂停/休眠。例如,用Get-NetAdapter | Select-Object Name,StatusPause要么Get-NetAdapter | Select-Object Name,Status | Where-Object {$_ -ne $null}Pause输出是:按Enter继续......:姓名状态---- ------Wi-Fi Up以太网断开连接而与Get-NetAdapter | Select-Object Name,Status | Format-TablePause输出是:姓名状态---- ------Wi-Fi Up以太网断开连接按Enter继续......:这里发生了什么?这是一个错误还是一个功能?
查看完整描述

3 回答

?
FFIVE

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的早期版本中注意到。


查看完整回答
反对 回复 2019-08-28
?
慕斯王

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中,一切都像在流水线操作的指令中不需要主机一样,然后这些指令以异步方式运行。


查看完整回答
反对 回复 2019-08-28
?
不负相思意

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-TableFormat-List或明确设置列宽Format-Table @{e='Name';w=50},则pause在输出后将调用。如果在每个输出对象上添加时序,那么您将看到,在300毫秒间隔后开始输出。 

查看完整回答
反对 回复 2019-08-28
  • 3 回答
  • 0 关注
  • 500 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信