1

Я новичок в powershell, и, похоже, у меня проблемы с концепцией труб. Насколько я понимаю:

  • Write-Host пишет "на консоли", но не может быть повторно использован / захвачен из других скриптов
  • Write-Output помещает что-то в трубу. Если содержимое канала не используется в другом месте, оно выводится на консоль. Вызывающий скрипт может использовать вывод.

Я знаю, что практически во всех языках сценариев вы можете писать в консоль из любого места, используя ее, вызывая сценарии и не влияя на возвращаемое значение функции.

Так:

  • Какая польза от этого? На данный момент дизайн выглядит элегантно, но не очень практично.
  • Как я могу записать в вывод скрипта из функции, не влияя на ее возвращаемое значение (нет, я не могу использовать [Write-Host][1])
  • Как я могу записать в вывод сценария из обратного вызова / события, как в

    $ect = Register-ObjectEvent -InputObject $ps -Action { Write-Somewhere $EventArgs.Data } -EventName 'ErrorDataReceived' 
    

Справочная информация: скрипт вызывается из файла оболочки, вызывается из файла оболочки, который вызывается из Jenkins. Write-Output правильно зарегистрирован, но я не могу использовать его везде. Я хочу избежать сброса текста во временный файл и прочитать его в конце, чтобы сэкономить время.

2 ответа2

1

Полезный эффект различия между Write-Host и Write-Output заключается в том, что вы можете вставить в свои функции протоколирование (Write-Host), не путая значения, которые они фактически возвращают своим вызывающим (Write-Output).

Говоря о возврате к вызывающим, простое разрешение значения из выражения или вызова командлета передаст его как вывод. Следовательно, 5 на строке и Write-Output 5 эквивалентны. Несколько хитрая концепция заключается в том, что скрипты PowerShell не имеют возвращаемых значений в том же смысле, что и большинство языков программирования. Возврат значения с ключевым словом Return неотличим от пропуска значения из выходного конвейера и последующего выхода из функции. Другими словами, 5; break такой же, как Return 5 . Выходные данные скрипта (которые могут быть несколькими объектами) являются возвращаемым значением.

Объекты, которые выходят из блоков сценариев, зарегистрированных как действия события, автоматически сохраняются в свойстве Output объекта задания события, что вы и возвращаете из Register-ObjectEvent если используете -Action для предоставления блока сценария. Вот пример сценария, который записывает текущую дату и время каждый раз, когда срабатывает таймер:

$timer = New-Object System.Timers.Timer
$timer.Interval = 2000
$myEvent = Register-ObjectEvent $timer -EventName 'Elapsed' -Action {Get-Date}
$timer.Start()

$myEvent получит объект задания из Register-ObjectEvent . $myEvent.Output будут постоянно увеличиваться, по одному на каждый запуск Get-Date в обработчике событий. (Есть некоторые автоматически определенные переменные, которые могут быть полезны в таких обработчиках.) В вашем случае, после завершения генерации обратных вызовов вы можете вывести $ect.Output для передачи захваченных данных в вызывающий скрипт.

В качестве альтернативы, если вы не хотите иметь дело с пользовательскими обработчиками событий, вы можете отключить блок сценария и вместо этого предоставить идентификатор источника, который называет подписку на событие. Мы могли бы заменить $myEvent из предыдущего примера следующим образом:

Register-ObjectEvent $timer -EventName 'Elapsed' -SourceIdentifier 'MyEvent'

Теперь события попадают в очередь событий, помеченную нашим идентификатором источника. Чтобы получить их позже, мы используем Get-Event:

Get-Event -SourceIdentifier 'MyEvent'
0

Сначала, если вам нужны подробности о том, как Write-Output работает (и должен работать), смотрите ответ BenN.

Ни Write-Output, ни Write-Host действительно не работают для меня. Но у Powershell есть больше возможностей для записи на экране и вывода каналов. Я решил использовать Write-Verbose. Я не контролирую вызывающий скрипт, но, к счастью, Verbose-канал уже объединен со стандартным выводом.

Если это не так, вам нужно вручную объединить вывод отладки со стандартным выводом:

.\test_writing_to_debug_output.ps1 4>&1 > a_logfile.txt

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .