Невозможно приостановить или спать после выбора объекта
В некоторых случаях, если я пытаюсь сделать паузу или спать после Select-Object
команда, пауза / сон происходит перед командой.
Например, с
Get-NetAdapter | Select-Object Name,Status
Pause
или же
Get-NetAdapter | Select-Object Name,Status | Where-Object {$_ -ne $null}
Pause
выход:
Нажмите Enter, чтобы продолжить...: Название Статус ---- ------ Wi-Fi Up Ethernet отключен
Тогда как с
Get-NetAdapter | Select-Object Name,Status | Format-Table
Pause
выход:
Название Статус ---- ------ Wi-Fi Up Ethernet отключен Нажмите Enter, чтобы продолжить...:
Что тут происходит? Это ошибка или особенность?
2 ответа
То, что вы видите, является следствием новой функции 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.
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 все работает так, как будто хост не нужен в инструкциях, которые передаются по конвейеру, тогда эти инструкции выполняются асинхронно.
Мне бы хотелось, чтобы такие люди, как @Keith Hill, смотрели на это поведение.