1

I am using System.Management.Automation.Runspaces.Pipleline to create a powershell pipeline instance and execute my powershell scripts in c# console application, the problem is that if the script end up with an error, then i don't know how to print that error on the console screen.

This is my code,

System.Management.Automation.Runspaces.Runspace PowershellRunspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
PowershellRunspace.Open();

System.Management.Automation.RunspacesPipeline PowershellPipeline = PowershellRunspace.CreatePipeline();
PowershellPipeline.Commands.AddScript(PowershellScript);
PowershellPipeline.Commands.AddScript("Out-String");
foreach (string IpAddress in ActiveSystemIPAddresses)
{

    PowershellPipeline.Commands.AddScript("Stop-Computer -ComputerName \"" + IpAddress + "\" -Credential $Credentials");
}
try
{
    Collection<PSObject> output = PowershellPipeline.Invoke();
    if (PowershellPipeline.HadErrors)
    {
        Console.WriteLine("Cannot shutdown this server IP");
    }
    PowershellPipeline.Stop();

    StringBuilder results = new StringBuilder();

    foreach (PSObject obj in output)
    {
        results.AppendLine(obj.ToString());
    }
    Console.WriteLine(results);
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}
PowershellRunspace.Close();

I can see the property Pipeline.HadErrors but it only rake me to the loop if there are errors detected, its doing anyhting to get the error message. My problem is how to get the actual error on the console screen?

Muhammad Areeb
  • 92
  • 2
  • 14

3 Answers3

8

Something like this should get you the errors.

var rs = RunspaceFactory.CreateRunspace();
rs.Open();
var ps = rs.CreatePipeline();
ps.Commands.AddScript("Get-Member");
ps.Commands.AddScript("ps");

try
{
    var result = ps.Invoke();

    if (ps.HadErrors)
    {
        var errors = ps.Error.ReadToEnd();
        foreach (var error in errors)
        {
            Console.WriteLine(error);
        }
    }

    foreach (var r in result)
    {
        Console.WriteLine(r);
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
    ps.Stop();
}
Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
4

With the recent changes, following works with Microsoft.powershell.5.referenceAssemblies in C#

var result = ps.Invoke();

if (ps.HadErrors)
{
    foreach (ErrorRecord error in ps.Streams.Error.ReadAll())
    {
        Console.WriteLine(error.ToString());
        // You can access error.FullyQualifiedErrorId or error.Exception if you needed to 
        //   be specific in what you were looking for when it failed.
    }
}
Jawad
  • 11,028
  • 3
  • 24
  • 37
0

To see the errors you can look at the collection PowerShell.Streams.Error.

If you wanted to do this natively in a PowerShell script and return the error you could wrap it in a try/catch and return the $error variable.

$error is a PowerShell variable where all errors are automatically added in an array. The first item in the array is always the newest error.