У меня проблема с неожиданным порядком запуска и возврата вещей в приведенном ниже сценарии Powershell.
Функция Write-ArrayToTable предназначена для вывода данных в массивах в форме, похожей на таблицу, с помощью пользовательского объекта.
Проблема в том, что когда я вызываю свою функцию Write-ArrayToTable, она не возвращает данные до тех пор, пока не вернется команда Read-Host.
Ниже приведен вывод запуска скрипта, а сам код ниже. Вывод таблицы должен отображаться ПЕРЕД вызовом Read-Host, но вместо этого удерживается до конца, а затем отображается.
Что мне не хватает? Любая помощь очень ценится!
Вывод:
Test: y
Label1 Label2
------ ------
Test1 Test3
Test2 Test4
y
Код:
Function Write-ArrayToTable{
param(
[String[]]$Names,
[Object[][]]$Data
)
for($i = 0;; ++$i){
$Props = [ordered]@{}
for($j = 0; $j -lt $Data.Length; ++$j){
if ($i -lt $Data[$j].Length){
$Props.Add($Names[$j], $Data[$j][$i])
}
}
if (!$Props.get_Count()){
break
}
[PSCustomObject]$Props
}
}
$arr1 = @("Test1","Test2")
$arr2 = @("Test3","Test4")
Write-ArrayToTable "Label1","Label2" $arr1,$arr2
Read-Host "Test"
Кроме того, нет гарантии, что ваш код будет генерировать табличный вывод — в PowerShell есть некоторые правила, которые определяют, использует ли поведение по умолчанию для форматирования вывода format-list или format-table — ваши тестовые примеры, вероятно, просто выбрали format-table, но если вы попробуете с одним вместо свойства вы можете увидеть, что оно использует format-list…
@mclayton Спасибо за эту информацию. Любая идея о лучшем способе получить желаемый результат вывода параллельного табличного отображения массивов? Не запрашивая код, просто общее направление для изучения.
Если вы переименуете свою функцию во что-то вроде Select-From2DArray, что более реалистично, то вы можете просто направить вывод из этого в Format-Table, и он всегда будет выводить в виде табличных данных.
Круто, у меня все работает благодаря вам и @stackprotector. Очень ценю информацию о том, что происходит под капотом. Помоги мне узнать больше!
Хотя я только что заметил, что это зубчатый массив, а не 2D-массив, так что, возможно, Select-FromJaggedArray было бы лучшим названием…
Чтобы добавить к комментариям Маклейтона: отсутствие синхронизации между выводом конвейера и выводом на хост (а также другими потоками вывода) ограничено PS v5+ и очень специфическим, хотя и все еще распространенным сценарием: неявно табличный вывод для типов, которые для них не определены данные форматирования. Неоптимальный обходной путь заключается в принудительном синхронном выводе конвейера с хостом (дисплеем) с помощью Out-Host. Подробнее см. связанный дубликат.





Вместо того, чтобы сбрасывать такие объекты:
[PSCustomObject]$Props
Вы можете быть более явным:
$Props | Out-String
Если вы хотите напечатать все объекты в одной таблице, сначала соберите их перед печатью:
Function Write-ArrayToTable{
param(
[String[]]$Names,
[Object[][]]$Data
)
$myProps = for($i = 0;; ++$i){
$Props = [ordered]@{}
for($j = 0; $j -lt $Data.Length; ++$j){
if ($i -lt $Data[$j].Length){
$Props.Add($Names[$j], $Data[$j][$i])
}
}
if (!$Props.get_Count()){
break
}
[PSCustomObject]$Props
}
$myProps | Format-Table
}
Поскольку проблема связана исключительно с отображением, лучше решать ее на этом уровне, а не переписывать, какие данные выводит функция: Write-ArrayToTable "Label1","Label2" $arr1,$arr2 | Out-Host будет делать. Это вызывает синхронный вывод на дисплей и, таким образом, решает исходную проблему, которая заключается в асинхронном выводе на дисплей, который вы получаете с неявно отформатированным выводом в виде таблицы, в результате чего приглашение Read-Host неожиданно отображается первым.
Вероятно, та же основная причина, что и в этом ответе @mklement0… stackoverflow.com/a/59331305/3156906 -
Format-Tableможет задерживать до 300 мс перед рендерингом вывода, к этому времениRead-Hostуже блокируется в ожидании ответа от пользователя, чтобы вы ничего не видели, покаRead-Hostне закончит.