порядок выполнения команд внутри блока сценария PowerShell

Сначала я был в восторге от PowerShell ScriptBlock, но недавно меня смутил порядок его выполнения внутри блоков. Например:

$test_block = {
  write-host "show 1"
  ps
  write-host "show 2"
  Get-Date
}

Результат при вызове $ test_block.Invoke ():

show 1
show 2
<result of command 'ps'>
<result of command 'get-date'>

Выполняются ли команды, которые что-то выводят, первыми?


person dave    schedule 28.10.2013    source источник


Ответы (2)


Такое поведение вызвано тем, что write-host не помещает вывод в конвейер. Остальные команды размещаются в конвейере, поэтому не выводятся на экран до тех пор, пока функция (invoke) не вернется.

Чтобы получить ожидаемое поведение, используйте вместо этого запись-вывод, результаты все команды будут возвращены в конвейер.

$test_block = {
  write-output "show 1"
  ps
  write-output "show 2"
  Get-Date
}

$test_block.Invoke()
person David Martin    schedule 28.10.2013

В дополнение к полезному ответу Дэвида Мартина:

Действительно, Write-Host предназначен для записи непосредственно на хост, который является консолью (терминалом) в сеансе PowerShell на основе окна консоли. То есть Write-Host намеренно обходит выходной поток успешных данных PowerShell, в который команды и выражения неявно отправляют свои данные.

Write-Output - это командлет, который выполняет запись в поток вывода успешных результатов, но его явное использование редко требуется; вы могли просто использовать "show 1" и "show 2" как есть.

Write-Host предназначен для создания пользовательских интерфейсов (печати (цветных) сообщений для информирования пользователя), а не для вывода данных.

Дополнительную информацию см. В нижнем разделе этого ответа.

Блоки сценариев ({ ... }) обычно вызываются с помощью &, оператора вызова, а не с помощью их .Invoke() метода.

.Invoke() действительно сначала собирает все данные потока успешного вывода, а затем выводит их при возврате из вызова метода, тогда как Write-Host вызовы выполняются немедленно.

Однако такое поведение не применяется к вызову с &:
Вызовы с & - а также прямой вызов команд в последовательности - также немедленно выводят объекты потока успеха, так что вы ' Получим ожидаемый порядок вывода.

$test_block = {
  write-host "show 1"
  ps
  write-host "show 2"
  Get-Date
}
# Use of & to call the script block results in the expected output order.
& $test_block

# show 1
# <ps output>
# show 2
# <get-date output>

Однако в PSv5 + все еще может быть проблема с упорядочением вывода, хотя ее причина не связана: неявный табличный вывод (подразумевается Format-Table) для вывода типы без предопределенного формата данных являются асинхронными для определения подходящей ширины столбцов.

См. Следующие примеры и этот ответ для получения дополнительной информации.

# OK: Output ordering as expected:
#     Get-Item outputs a System.IO.DirectoryInfo instance for which
#     format data is predefined.
PS> Write-Host '------- 1'; Get-Item /; Write-Host '------- 2'
------- 1


    Directory:


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d--hs-        12/5/2019   3:34 PM                C:\
------- 2
# !! OUT OF SEQUENCE, because Select-Object creates [pscustomobject] instances
# !! for which no format data is predefined, and custom object with 4 or fewer
# !! properties triggers implicit Format-Table display.
PS> Write-Host '------- 1'; Get-Item / | Select-Object FullName; Write-Host '------- 2'
------- 1

------- 2
FullName
--------
C:\

Вы можете решить эту проблему, направив команду вне последовательности в Out-Host, но обратите внимание, что это предотвращает дальнейшую программную обработку ее вывода:

# Using Out-Host fixes the output-ordering problem, but prints
# the data to the host (display) only.
PS> Write-Host '------- 1'; Get-Item / | Select-Object FullName | Out-Host; Write-Host '------- 2'
------- 1

FullName
--------
/

------- 2

См. этот ответ для потенциального - но неоптимального - решения, которое не требует Out-Host и вместо этого отправляет строки для отображения в поток вывода успеха, обеспечивающий раскрашивание с помощью встроенных управляющих последовательностей VT (виртуального терминала).

person mklement0    schedule 06.12.2019