PowerShell中Register-ObjectEvent触发Write-Error不显示控制台报错
问题原因
Register-ObjectEvent的-Action脚本块运行在独立的后台运行空间中,这个运行空间的错误流、输出流默认不会关联到主控制台的对应流。所以Action里的Write-Error只是在后台运行空间内产生了错误,不会自动同步显示到主控制台。
解决方法
提供三种可行的实现方案:
方案1:直接调用主机UI输出错误
用$Host.UI.WriteErrorLine()绕过运行空间流的隔离,直接向控制台输出带错误样式的文本:
$ScriptBlock = { Start-Sleep 3 Write-Error 'sample Error' } $ps = [powershell]::Create() $null = $ps.AddScript($ScriptBlock) $handle = $ps.BeginInvoke() $e = Register-ObjectEvent -InputObject $ps -EventName 'InvocationStateChanged' -Action { Write-Warning 'event fired' if($event.Sender.HadErrors) { foreach($ErrorItem in $event.Sender.Streams.Error) { Write-Warning ('[Error Exception] {0}' -f $ErrorItem.Exception) # 直接输出错误到控制台 $Host.UI.WriteErrorLine($ErrorItem.Exception.Message) } } }
方案2:在主运行空间执行Write-Error
保存主运行空间的引用,在Action中调用主运行空间执行Write-Error,确保错误输出到主控制台:
$ScriptBlock = { Start-Sleep 3 Write-Error 'sample Error' } # 保存主运行空间引用 $mainRunspace = [runspacefactory]::CreateRunspace() $mainRunspace.Open() $ps = [powershell]::Create() $null = $ps.AddScript($ScriptBlock) $handle = $ps.BeginInvoke() $e = Register-ObjectEvent -InputObject $ps -EventName 'InvocationStateChanged' -Action { param($mainRunspace) Write-Warning 'event fired' if($event.Sender.HadErrors) { foreach($ErrorItem in $event.Sender.Streams.Error) { Write-Warning ('[Error Exception] {0}' -f $ErrorItem.Exception) # 在主运行空间执行Write-Error $psMain = [powershell]::Create().AddScript({ param($ex) Write-Error -Exception $ex }).AddArgument($ErrorItem.Exception) $psMain.Runspace = $mainRunspace $null = $psMain.Invoke() $psMain.Dispose() } } } -MessageData $mainRunspace
方案3:事后收集事件错误输出
如果不需要实时显示,可在事件触发后通过Get-Event提取Action产生的错误信息:
# 执行原脚本后,运行以下命令获取错误内容 Get-Event -SourceIdentifier $e.Name | Select-Object -ExpandProperty MessageData
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

