Передача аргументов в скрипт-блок Action-EngineEvent - PullRequest
2 голосов
/ 26 марта 2019

Я хочу перехватить сценарий PowerShell по окончании, чтобы я мог выполнить некоторую окончательную обработку до его остановки.Register-EngineEvent -SourceIdentifier PowerShell.Exiting, кажется, способ сделать это, но он не работает ни для чего, кроме тривиальных приложений.

Работают простые примеры.Например:

Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {write-host "This is trivial"}

напечатает «Это тривиально», когда сценарий завершится.Однако любой блок действий, которому нужны данные, переданные ему, не получает эти данные.Например:

Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {write-host ">> " $($event.MessageData)} -MessageData "This doesn't work"

будет печатать только две ведущие угловые скобки, а не строку «Это не работает».

Обратите внимание, что я вызываю сценарий из командной строки(cmd.exe) и именно там Write-Host в конечном итоге печатает после выхода из PowerShell.

Кроме того, за исключением автоматических переменных $Event, все остальные, такие как $Sender,$Args, $EventArgs и т. Д. Не заселены.Также некоторые свойства $Event не заполняются.Например, $Event.ComputerName ничего не печатает, а $Event.TimeGenerated печатает текущую дату и время.У моего компьютера есть имя.

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

Я потратил довольно много времени на поиск веб-сайтов, но я не нашел примеров, когда они передают данные в блок действий для Register-EngineEvent.

sleep 1
write-host "Starting"
sleep 1
write-host "Finished"
Register-EngineEvent -SourceIdentifier PowerShell.Exiting -MessageData "This doesn't work" -Action {write-host ">> " $($event.MessageData)}
sleep 2

Я ожидал бы, что этот маленький скрипт выведет «Starting», затем 1 секунду позже «Finished», а затем, еще через 2 секунды, обработчик событий выведет «>> Это не работает».Я получаю первые два сообщения, но все, что я получаю от обработчика, это «>>».

Я работаю в Windows 10 с Powershell V5.Я не запускаю его в ISE.Я использую командную строку powershell -file .\try6.ps1, где try6.ps1 - это скрипт, который я включил выше.

Если кто-нибудь может подсказать, что я делаю неправильно, или альтернативные способы сделать это, было бы замечательно, но даже если этопросто это известная ошибка или что я неправильно понял, что такое PowerShell.exiting или Register-EngineEvent, и они не могут быть использованы так, как я пытаюсь, это также будет очень полезно.

1 Ответ

0 голосов
/ 26 марта 2019

Примечание : хотя этот ответ содержит, надеюсь, полезную справочную информацию , он не решает проблему ОП о желании передать пользовательские данные события в PowerShell.Exiting обработчик событий.

То, с чем столкнулся Колин, это очевидно известная ошибка : см. эту проблему GitHub .


Как правило, просто для пояснения: событие PowerShell.Exiting возникает только при выходе из сеанса PowerShell , а не сценария , запущенного внутри сеанса .

Использование его в самом запущенном сеансе (в отличие от его использования в удаленном сеансе, который перенаправляет событие вызывающей стороне) ограничивает вас:

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

Вы запускаете сценарий локально через интерфейс командной строки PowerShell, powershell.exe, что означает, что указанные выше ограничения относятся к вам.

Автоматические переменные, связанные с событиями, описанные в about_Automatic_Variables , по-видимому, не содержат много информации при возникновении события, как демонстрирует следующая команда:

PS> powershell -c '$null = 
     Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
      $Event, $EventSubscriber, $Sender, $EventArgs, $Args | Out-string | Write-Host 
     }'
ComputerName     :
RunspaceId       : 1a763430-5cd8-4b74-aaaf-7a90e514518d
EventIdentifier  : 1
Sender           :
SourceEventArgs  :
SourceArgs       : {}
SourceIdentifier : PowerShell.Exiting
TimeGenerated    : 3/26/19 12:15:48 AM
MessageData      :

SubscriptionId   : 1
SourceObject     :
EventName        :
SourceIdentifier : PowerShell.Exiting
Action           : System.Management.Automation.PSEventJob
HandlerDelegate  :
SupportEvent     : False
ForwardEvent     : False
  • $Event существует и предоставляет идентификатор пространства выполнения и отметку времени, отражающую время события.

    • $Event.ComputerName предположительно заполняется, только если событие было перенаправлено (через Register-EngineEvent 's -Forward) с другого компьютера в контексте удаленного взаимодействия; если свойство пустое, это означает, что событие сработало на локальном компьютере.
  • $EventSubscriber существует, но не содержит никакой полезной информации.

  • $EventArgs, $Sender и $Args не заполнены.

Учитывая вышесказанное, вы можете упростить вывод, чтобы содержать только отметку времени события и имя локального компьютера:

PS> powershell -c '
     $null = 
       Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
       [pscustomobject] @{ TimeGenerated = $Event.TimeGenerated; ComputerName = $env:COMPUTERNAME }| Format-List | Out-String | Write-Host 
     }
     # ... call your script 
     .\try6.ps1
   '


TimeGenerated : 3/26/2019 8:57:53 AM
ComputerName  : Workstation10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...