Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
336 views
in Technique[技术] by (71.8m points)

powershell - Unable to Pause or Sleep after Select-Object

In some cases, if I try to pause or sleep after a Select-Object command, the pause/sleep occurs before the command.

For example, with

Get-NetAdapter | Select-Object Name,Status
Pause

or

Get-NetAdapter | Select-Object Name,Status | Where-Object {$_ -ne $null}
Pause

the output is:

Press Enter to continue...:

Name     Status
----     ------
Wi-Fi    Up
Ethernet Disconnected

Whereas with

Get-NetAdapter | Select-Object Name,Status | Format-Table
Pause

the output is:

Name     Status
----     ------
Wi-Fi    Up
Ethernet Disconnected

Press Enter to continue...:

What's going on here? Is this a bug or a feature?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

What you see is a consequences of new PowerShell v5 feature. Format-Table now collect input for 300 milliseconds to find better column width. It work this way even if you explicitly specify -AutoSize:$false.

When you type command in command prompt, that command implicitly piped to single instance of Out-Default command. The Out-Default command then decide how to format objects and print them on PowerShell host (console). So that, even if you does not use Format-Table directly in your code, that does not mean that you does not have Format-Table in your pipeline. Out-Default can decide to format objects as table and use Format-Table internally.

Custom objects with four or less properties and without custom formatting defined for them in format files are formatted as table. By using Select-Object with two properties you produce exactly that objects.

PowerShell pipeline is single-threaded. That means that Format-Table can not just output all collected objects when 300 milliseconds interval elapsed. Format-Table have to wait till you pipe next item to it (process block invoked) or end of pipeline reported (end block invoked).

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>

Implicit Format-Table does not print anything (strictly saying it print empty line) before first Pause because it still waiting for more input objects (300 milliseconds not yet elapsed) to decide on column width. When first object (#1) come after 300 milliseconds interval (assuming that you are not to fast on pressing Enter), then Format-Table decide on column width and print all collected objects. Any further objects will be printed without delay, but them can not affect column width anymore. If value is to big for column it will be truncated.

PS> Get-NetAdapter | Select-Object Name,Status | Format-Table
>>> Pause

Name     Status
----     ------
Ethernet Up


Press Enter to continue...:
PS>

With this code, end block of explicit Format-Table will be executed before Pause. In end block Format-Table know that it already got all the input, so it can decide on column width and output all collected objects right away. Implicit Out-Default see that formatting objects from Format-Table output, and Out-Default know that them does not need any addition formatting and print them on host (console) right away as well. So whole table got printed before Pause invoked.

Notice the difference in placement of end of table mark (two empty lines). In first example it placed after last Pause. It is because implicit Format-Table still active and still wait, that you pass additional object to it. Only when your command fully completed Format-Table acknowledge end of input and output end of table mark. In second example, explicit Format-Table completes before Pause, so whole table (including end of table mark) got printed before Pause command.

The difference in placement of end of table mark can be noticed it previous versions of PowerShell as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...