Как определить пользовательский тип слота, который не является списком?

Что вы видите, это последствия новой функции 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 будет выполнен конечный блок явного Format-Table. В конце блока Format-Table известно, что он уже получил все входные данные, поэтому он может выбирать ширину столбца и сразу выводить все собранные объекты. Неявные Out-Default видят, что объекты форматирования из выхода Format-Table и Out-Default знают, что им не требуется форматирование добавок и их печать на хосте (консоли) сразу же. Итак, вся таблица была напечатана до Pause.

Обратите внимание на разницу в размещении конца метки таблицы (две пустые строки). В первом примере он помещается после последнего Pause. Это потому, что неявный Format-Table все еще активен и все еще ждет, что вы передаете ему дополнительный объект. Только когда ваша команда полностью завершена Format-Table, подтвердите завершение ввода и вывода конца таблицы. Во втором примере явная Format-Table завершается до Pause, поэтому вся таблица (включая конец таблицы) печатается перед командой Pause.

Разница в размещении конца метки таблицы может быть заметил и предыдущие версии PowerShell.

30
задан thetaiko 1 December 2015 в 22:27
поделиться