Error handling using process c#

2019-04-14 08:00发布

问题:

I have created a console application using C#, and I called it from another Windows Forms application using Process.

Below is my code for Console Application

   static void Main(string[] args)
        {
            try
            {
                // ...my code
            }
            catch (Exception)
            {

                throw;
            }
        }

Below is code for call the exe of Console application from the window application using process

    public void CallExe()
    {
        try
        {                              
            Process proc = new Process();
            proc.StartInfo.FileName = @"D:\Debug\console1.exe";
            proc.StartInfo.Arguments = "My args";
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            proc.Start();              
            proc.WaitForExit();              
            string stdout = proc.StandardOutput.ReadToEnd();
            string stderr = proc.StandardError.ReadToEnd();
            proc = null;
        }

        catch (Exception ex)
        {

            throw ex;
        }
    }

Now, What I want is when any error comes from the console application it directly throws to my window application catch block. Or can I get error message to my window application which is thrown by console application ?

回答1:

You are not capturing anything from the process you run. You can't call ReadToEnd on both streams as it will block one or the other from producing results. If you want to capture both the stdout as stderr you'll need to subscribe to the DataReceived events and store the data from the event arguments.

The following code in your windows forms application should look like this:

Process proc = new Process();
proc.StartInfo.FileName = @"console.exe";
proc.StartInfo.Arguments = "My args";
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

//store outcome of process
var errors = new StringBuilder();
var output = new StringBuilder();
var hadErrors = false;

// raise events
proc.EnableRaisingEvents = true;

// capture normal output
proc.OutputDataReceived += (s, d) => { 
    output.Append(d.Data); 
};

// Capture error output
proc.ErrorDataReceived += (s, d) => { 
    if (!hadErrors)
    {
        hadErrors = !String.IsNullOrEmpty(d.Data);
    }
    errors.Append(d.Data); 
};

proc.Start();
// start listening on the stream
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();

proc.WaitForExit();
string stdout = output.ToString();
string stderr = errors.ToString();

if (proc.ExitCode !=0 || hadErrors)
{
    MessageBox.Show("error:" + stderr);
}

In the test console application you can now write to stderr and set an Exitcode if you like:

try
{
    Console.WriteLine("Ready ...");
    var cmd = Console.ReadLine();
    if (cmd == "e")
    {
        throw new Exception("boom");
    } else
    {
        Console.WriteLine("success!");
    }
    Environment.ExitCode = 0;
}
catch(Exception e)
{
    // write to stderr
    Console.Error.WriteLine(e.Message);
    // exit code to 1
    Environment.ExitCode = 1;
}