在Pipeline.Invoke抛出后在C#中捕获Powershell输出

我正在从C#应用程序运行Powershell测试脚本。 由于cmdlet错误导致管道失败,导致pipe.Invoke()抛出exception。

我能够捕获关于exception所需的所有信息,但是我希望能够显示脚本的输出到那时为止。 我没有运气,因为抛出exception时结果似乎为null。

有什么我想念的吗? 谢谢!

m_Runspace = RunspaceFactory.CreateRunspace(); m_Runspace.Open(); Pipeline pipe = m_Runspace.CreatePipeline(); pipe.Commands.AddScript(File.ReadAllText(ScriptFile)); pipe.Commands.Add("Out-String"); try { results = pipe.Invoke(); } catch (System.Exception) { m_Runspace.Close(); // How can I get to the Powershell output that comes before the exception? } 

不确定这是否有用。 我猜你正在运行V1。 这种V2方法不会抛出并打印结果:

 Hello World 67 errors string script = @" 'Hello World' ps | % { $_.name | out-string1 } "; PowerShell powerShell = PowerShell.Create(); powerShell.AddScript(script); var results = powerShell.Invoke(); foreach (var item in results) { Console.WriteLine(item); } if (powerShell.Streams.Error.Count > 0) { Console.WriteLine("{0} errors", powerShell.Streams.Error.Count); } 

我最终使用的解决方案是实现我们自己的PSHost来处理PowerShell的输出。 最初的信息来自“建筑物”中的http://community.bartdesmet.net/blogs/bart/archive/2008/07/06/windows-powershell-through-ironruby-writing-a-custom-pshost.aspx自定义PS主机“部分。

在我的情况下,它确实需要使用自定义PSHostRawUserInterface。

以下是对所做工作的快速概述。 我只列出了我实际上已经实现的函数,但是有许多只是包含throw new NotImplementedException();

 private class myPSHost : PSHost { (Same as what the above link mentions) } private class myPSHostUI : PSHostUserInterface { private myPSHostRawUI rawui = new myPSHostRawUI(); public override void Write // all variations public override PSHostRawUserInterface RawUI { get { return rawui; } } } private class myPSHostRawUI : PSHostRawUserInterface { public override ConsoleColor ForegroundColor public override ConsoleColor BackgroundColor public override Size BufferSize } 

我也有同样的问题。 pipe.Invoke()抛出exception时获取输出的最简单方法是使用Invoke(IEnumerable输入,IList输出)

示例显示了如何以正确的顺序获得所有输出,错误,减弱等

PowerShell脚本

 Write-Output "Hello world" Write-Error "Some error" Write-Warning "Some warning" throw "Some exception" 

C#

 List RunLog = new List(); using (System.Management.Automation.PowerShell psInstance = System.Management.Automation.PowerShell.Create()) { psInstance.AddScript(_Script); psInstance.Streams.Error.DataAdded += (sender, args) => { ErrorRecord err = ((PSDataCollection)sender)[args.Index]; RunLog.Add($"ERROR: {err}"); }; psInstance.Streams.Warning.DataAdded += (sender, args) => { WarningRecord warning = ((PSDataCollection)sender)[args.Index]; RunLog.Add($"WARNING: {warning}"); }; ... etc ... var result = new PSDataCollection(); result.DataAdded += (sender, args) => { PSObject output = ((PSDataCollection)sender)[args.Index]; RunLog.Add($"OUTPUT: {output}"); }; try { psInstance.Invoke(null, result); } catch(Exception ex) { RunLog.Add($"EXCEPTION: {ex.Message}"); } }