Answered by:
Powershell retrieving pipeline errors in C#

Question
-
Hello,
I'm trying to retrieve errors from executing remote Powershell commands via C#. I'm trying to use this snippet of code as shown here but I do not get the pipeline.Streams property available. Can anyone tell me what is wrong here?
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Management.Automation; using System.Management.Automation.Remoting; using System.Management.Automation.Runspaces; using System.Security; namespace O365PS { class Program { static void Main(string[] args) { string userName = "admin@somecompany.com"; string password = "Password"; // Encrypt password using SecureString class SecureString securePassword = new SecureString(); foreach (char c in password) { securePassword.AppendChar(c); } PSCredential credential = new PSCredential(userName, securePassword); // Connection information object required to connect to the service WSManConnectionInfo connectionInfo = new WSManConnectionInfo( new Uri("https://ps.outlook.com/powershell"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic; connectionInfo.MaximumConnectionRedirectionCount = 2; // Create runspace on remote Exchange server using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo)) { runspace.Open(); using(PowerShell ps = PowerShell.Create()) { ps.Runspace = runspace; string[] members = new string[] { "user1@somecompany.com", "user2@somecompany.com", "user3@somecompany.com" }; foreach (string member in members) { Command command = new Command("Add-DistributionGroupMember"); command.Parameters.Add("Identity", "test"); command.Parameters.Add("Member", member); Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.Add(command); try { Collection<PSObject> results = pipeline.Invoke(); Collection<ErrorRecord> errors = pipeline.Streams.Error.ReadAll(); // Streams property is not available if (errors != null && errors.Count > 0) { foreach (ErrorRecord er in errors) { Console.WriteLine(er.Exception.ToString()); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } } Console.WriteLine("Operation completed"); Console.ReadKey(); } } }
Thanks.Wednesday, November 30, 2011 10:49 AM
Answers
-
I was able to get the pipeline error as below. For some reason, the ReadToEnd() method always returned a null for me, so I just used the Read() method to get the error.
results = pipeline.Invoke(); if (pipeline.Error.Count > 0) { var error = pipeline.Error.Read() as Collection<ErrorRecord>; if (error != null) { foreach (ErrorRecord er in error) { Console.WriteLine("[PowerShell]: Error in cmdlet: " + er.Exception.Message); } } }
- Marked as answer by preambleMe Sunday, December 4, 2011 2:04 AM
Sunday, December 4, 2011 2:04 AM
All replies
-
Hello,
Can anyone help me out on this? This MSDN article says:
Streams: Gets the data streams that contain any messages and error reports that were generated when the pipeline of the PowerShell object is invoked.
But I don't get the Streams property available in Intellisense.
Any help on this is greatly appreciated.
Thanks.
Wednesday, November 30, 2011 3:30 PM -
I was able to get the pipeline error as below. For some reason, the ReadToEnd() method always returned a null for me, so I just used the Read() method to get the error.
results = pipeline.Invoke(); if (pipeline.Error.Count > 0) { var error = pipeline.Error.Read() as Collection<ErrorRecord>; if (error != null) { foreach (ErrorRecord er in error) { Console.WriteLine("[PowerShell]: Error in cmdlet: " + er.Exception.Message); } } }
- Marked as answer by preambleMe Sunday, December 4, 2011 2:04 AM
Sunday, December 4, 2011 2:04 AM -
Thanks a lot.This was of great help.
But for me error object was still null.Following snippet worked fine
if (pipeline.Error.Count > 0)
{
StringBuilder err = new StringBuilder();
while (!pipeline.Error.EndOfPipeline)
{
err.AppendLine(pipeline.Error.Read().ToString());
}
}Hope this helps someone
- Proposed as answer by Shanmuga Thursday, March 10, 2016 11:50 AM
Thursday, March 10, 2016 11:50 AM -
Thanks, this was really helpful for me! I refined & combined both of your snippets, as I looked into it and if it is not an ErrorRecord-Collection, it seems it is an ErrorRecord (I'm throwing the exceptions, feel free to change) :
if (pl.Error.Count > 0) { StringBuilder err = new StringBuilder(); while (!pl.Error.EndOfPipeline) { var x = pl.Error.Read(); if (x is Collection<ErrorRecord>) { throw (x as Collection<ErrorRecord>).First().Exception; } if (x is ErrorRecord) { throw (x as ErrorRecord).Exception; } err.AppendLine(pl.Error.Read().ToString()); } throw new Exception("Error executing PowershellCommand : " + err); }
Casting could be optimized (is and as result in double type inspection), but I left it this way as it's not performance critical in my case, and in my opinion is easier to read.
- Edited by Compufreak345 Wednesday, March 8, 2017 12:44 PM
Wednesday, March 8, 2017 12:42 PM