Порядок выполнения команд внутри блока сценариев 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'>

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

1 ответ

Решение

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

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

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

$test_block.Invoke()

Чтобы дополнить полезный ответ Дэвида Мартина:

На самом деле, 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 (виртуального терминала).

Другие вопросы по тегам