Почему вывод [PSCustomObject] меняет порядок выполнения

avatar
Frank
9 августа 2021 в 05:41
49
1
0

Почему во второй паре команд Read-Host обрабатывается до вывода объекта?

PS > (1..3).ForEach{ @{ a=$_ } }; Read-Host 'pause1'
Name                           Value                                                                                                          
----                           -----                                                                                                          
a                              1                                                                                                              
a                              2                                                                                                              
a                              3                                                                                                              
pause1: 

PS > (1..3).ForEach{ [PSCustomObject]@{ a=$_ } }; Read-Host 'pause2'
pause2: 
a
-
1
2
3

Я бы сказал, что это только начало происходить. Сценарий, который выводит [PSCustomObject], теперь должен завершиться до того, как будет виден вывод. Вход в отладчик после цикла, но до завершения скрипта означает, что вывод не виден.

Источник
iRon
9 августа 2021 в 06:57
2

Порядок выполнения не изменяется, но элементы в конвейере удерживаются до завершения командной строки, прежде чем они будут выпущены на вывод по умолчанию (то есть на дисплей). Вы можете заставить их отображаться с помощью специального командлета Write-Host: (1..3).ForEach{ [PSCustomObject]@{ a=$_ } } |Write-Host; Read-Host 'pause2'

Frank
9 августа 2021 в 21:34
0

Итак, это не порядок выполнения, но ваш ответ не решает проблему, заключающуюся в том, что объект не выводится на хост, или объясняет, почему поведение отличается, когда объект представляет собой простую хеш-таблицу. Кроме того, что, если это был цикл foreach, который не поддерживает конвейерную передачу ForEach($i in (1..3)){ [PSCustomObject]@{ a=$_ } } |Write-Host; Read-Host 'pause2'? Что, если бы у вас была точка останова внутри цикла и вы хотели бы увидеть каждый объект до завершения всего цикла?

Ответы (1)

avatar
iRon
9 августа 2021 в 13:56
0

Порядок выполнения не изменяется, но элементы в конвейере удерживаются до тех пор, пока последовательность команд не будет завершена, прежде чем они будут переведены в выходные данные по умолчанию (то есть на дисплее).

Доказать

  1. Введите ответ на командлет Read-Host 'pause2' и обратите внимание, что ответ добавляется в конце конвейера:
pause2: Test
a
-
1
2
3
Test
  1. Добавить временные метки для тестирования:
(1..3).ForEach{ [PSCustomObject]@{ a=(Get-Date).ToString('HH:mm:ss.fffffff') } } ; Read-Host (Get-Date).ToString('HH:mm:ss.fffffff')
15:41:29.1931049:
a
-
15:41:29.1916159
15:41:29.1918194
15:41:29.1919053

Решение

Явное принудительное немедленное отображение элементов конвейера с помощью специального командлета Write-Host:

(1..3).ForEach{ [PSCustomObject]@{ a=$_ } } |Write-Host; Read-Host 'pause2'
@{a=1}
@{a=2}
@{a=3}
pause2:
Frank
9 августа 2021 в 21:29
0

Итак, это не порядок выполнения, но ваше решение не решает проблему, заключающуюся в том, что объект не выводится на хост. Что, если это был цикл foreach, который не поддерживает конвейер ForEach($i in (1..3)){ [PSCustomObject]@{ a=$_ } } |Write-Host; Read-Host 'pause2'? Что, если бы у вас была точка останова внутри цикла и вы хотели бы увидеть каждый объект до завершения всего цикла? Вы также не объясняете, почему поведение отличается, когда объект представляет собой простую хеш-таблицу.