4

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 ?

stuartd
  • 70,509
  • 14
  • 132
  • 163
Chetan Sanghani
  • 2,058
  • 2
  • 21
  • 36
  • 2
    You can't catch an error that occurs in another process, but you _can_ return an exit code from the console app. – stuartd Sep 02 '16 at 12:30
  • Can I get ex.message from console application ? – Chetan Sanghani Sep 02 '16 at 12:31
  • 1
    You can [specify an exit code](http://stackoverflow.com/questions/155610/how-do-i-specify-the-exit-code-of-a-console-application-in-net) which is an integer, and pick it up from [`Process.ExitCode`](https://msdn.microsoft.com/en-us/library/system.diagnostics.process.exitcode(v=vs.110).aspx). Or you could read/write whatever you want from/to StandardOutput or StandardError – stuartd Sep 02 '16 at 12:32
  • what you CAN do is interprocess communication: catch the exception in your console process, have a pipe to your other process, and write a serialized exception onto that pipe ... read it on the other side, and... maybe even give commands back on what to do next?! – DarkSquirrel42 Sep 02 '16 at 12:33
  • @DarkSquirrel42: Thanks a lot. Can I have small example for that ? – Chetan Sanghani Sep 02 '16 at 12:35
  • 1
    an IPC example? ... here you go... https://msdn.microsoft.com/en-US/en-en/library/bb546085(v=vs.110).aspx – DarkSquirrel42 Sep 02 '16 at 16:03

1 Answers1

9

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;
}
rene
  • 41,474
  • 78
  • 114
  • 152