首页 > 解决方案 > 将参数传递给 Register-EngineEvent 动作脚本块

问题描述

我想在 PowerShell 脚本完成时捕获它,以便在它停止之前进行一些最终处理。Register-EngineEvent -SourceIdentifier PowerShell.Exiting似乎是这样做的方法,但它不适用于琐碎的应用程序以外的任何东西。

简单的例子有效。例如:

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

脚本完成后将打印“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

我希望那个小脚本打印“开始”,然后在 1 秒后打印“完成”,然后再过 2 秒,事件处理程序打印“>> 这不起作用”。我确实收到了前两条消息,但我从处理程序中得到的只是“>>”。

我在带有 Powershell V5 的 Windows 10 上运行。我没有在 ISE 中运行它。我使用命令行,上面包含的脚本powershell -file .\try6.ps1在哪里。try6.ps1

如果有人可以建议我做错了什么或这样做的替代方法会很棒,但即使它只是一个已知的错误或者我误解了什么PowerShell.exiting或是什么Register-EngineEvent并且它们不能以我的方式使用我正在尝试这也会很有帮助。

标签: powershelleventsevent-handling

解决方案


注意:虽然此答案包含希望有用的背景信息,但它并不能解决 OP想要将自定义事件数据传递给PowerShell.Exiting事件处理程序的问题。

Colin 遇到的显然是一个已知错误:请参阅GitHub 问题 #7000


通常,只是为了澄清:该PowerShell.Exiting事件仅在退出 PowerShell session时触发,而不是在 session 中运行的脚本

在运行会话本身中使用它(而不是在将事件转发给调用者的远程会话中使用它)限制您:

  • 会话结束时采取幕后行动
  • usingWrite-Host写入调用进程可能看到的输出(使用隐式输出或Write-Output不再是一个选项,因为 PowerShell 的输出流在事件触发时不再可用)。

您正在通过 PowerShell 的 CLI 在本地运行脚本,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存在,并提供运行空间 ID 和反映事件时间的时间戳。

    • $Event.ComputerName大概只有在远程处理的上下文中从另一台计算机转发事件(通过Register-EngineEvent-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

推荐阅读