// To use StandardOutput, you must set ProcessStartInfo.UseShellExecute to false, and you must set
// ProcessStartInfo.RedirectStandardOutput to true. Otherwise, reading from the StandardOutput stream throws an exception.
// What is going to do Mono with stdout, stdin and stderr depending on this value?
+ // Answer: true or false is the same (from the stdout/stderr/stdin point of view) BUT IF THIS PROPERTY
+ // HAS TRUE VALUE YOU MAY NOT REDIRECT stdout/stderr/stdin STREAMS. SO, THIS PROPERTY
+ // ENABLES US TO REDIRECT STREAMS (by means of pipes). WHEN UseShellExecute HAS TRUE VALUE TRYING
+ // TO SET TRUE VALUE IN RedirectStandardOutput/RedirectStandardInput/RedirectStandardError
+ // WILL THROW EXCEPTION.
startInfo.UseShellExecute = false;
- // Redirect the standard output of the subprocess command.
- // What is going to do Mono with stdout? Some pipe, I guess.
+ // Redirect the standard output of the child process command.
+ // What is going to do Mono with stdout? Answer: piped stdout from child to this C# parent process.
+ // TRUE VALUE REQUIRES UseShellExecute=false
startInfo.RedirectStandardOutput = true;
- // What is going to do Mono with stdin?
+ // What is going to do Mono with stdin? Answer: stdin the same as child's parent process (this C# process)
+ // TRUE VALUE REQUIRES UseShellExecute=false
startInfo.RedirectStandardInput = false;
- // What is going to do Mono with stderr?
+ // What is going to do Mono with stderr? Answer: stderr the same as child's parent process (this C# process)
+ // TRUE VALUE REQUIRES UseShellExecute=false
startInfo.RedirectStandardError = false;
// What is going to do Mono with this value? What if I am running a GTK (GUI application)
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
+ // Encoding
+ startInfo.StandardOutputEncoding = Encoding.UTF8;
+ // It is only supported when stream is redirected.
+ // startInfo.StandardErrorEncoding = Encoding.UTF8;
+
startInfo.Arguments = arguments;
startInfo.FileName = command;
process.StartInfo = startInfo;
- // When is Mono going to call my event implementation? Every time the subprocess writes to stdout?
+ // What is going to do Mono depending on this value? :/
+ // true if the Exited event should be raised when the associated child process is terminated
+ // (through either an exit or a call to Kill); otherwise, false. The default is false.
+ // The EnableRaisingEvents property indicates whether the component should be notified
+ // when the operating system has shut down a child process. The EnableRaisingEvents property
+ // is used in asynchronous processing to notify your application that a child process has exited.
+ // To force your application to synchronously wait for an exit event (which interrupts
+ // processing of the application until the exit event has occurred), use the WaitForExit method.
+ process.EnableRaisingEvents = false;
+
+ // When is Mono going to call my event implementation? Every time the child process writes to stdout?
// From here: http://msdn.microsoft.com/en-us/library/vstudio/system.diagnostics.process.outputdatareceived%28v=vs.110%29.aspx
- // Thereafter, the OutputDataReceived event signals each time the process writes a line to the
- // redirected StandardOutput stream, until the process exits or calls CancelOutputRead.
+ // Thereafter, the OutputDataReceived event signals each time the child process writes a line to the
+ // redirected StandardOutput stream, until the child process exits or calls CancelOutputRead.
// That behaviour is weird (IMHO) Check out the Mono implementation!!!
// Set our event handler to asynchronously read the standard output.
process.OutputDataReceived += new DataReceivedEventHandler(
delegate(object sendingProcess, DataReceivedEventArgs outLine)
{
// Collect the command output.
- // To asynchronously collect the redirected StandardOutput or StandardError stream output of a process, you must create
- // a method that handles the redirected stream output events. The event-handler method is called when the process writes
+ // To asynchronously collect the redirected StandardOutput or StandardError stream output of a child process, you must create
+ // a method that handles the redirected stream output events. The event-handler method is called when the child process writes
// to the redirected stream. The event delegate calls your event handler with an instance of DataReceivedEventArgs.
- // The Data property contains the text line that the process wrote to the redirected stream.
+ // The Data property contains the text line that the child process wrote to the redirected stream.
if (!String.IsNullOrEmpty(outLine.Data))
{
// Add the text to the collected output.
processOutput.Append(Environment.NewLine + outLine.Data);
}
});
- // Taken from http://stackoverflow.com/questions/285760/how-to-spawn-a-process-and-capture-its-stdout-in-net
- // I do not think this is the right way to read the output stream!!!!
- // My event handler will be called (see documentation) every time the process writes a line to the output stream but
- // with this code I will be reading the output stream until it is closed by the process. So, I guess, we could end
- // up having multiple event handlers reading from the same stream (output stream) Each handler was called each time
- // the process wrote a line to the output stream. :/
- // process.OutputDataReceived += new DataReceivedEventHandler(
- // delegate(object sender, DataReceivedEventArgs e)
- // {
- // using (StreamReader output = process.StandardOutput)
- // {
- // string data = output.ReadToEnd();
- // processOutput.Append(data);
- // }
- // });
- // Don't mix using statements and lambda expressions :(
- // http://blogs.msdn.com/b/jaredpar/archive/2008/07/16/don-t-mix-using-statements-and-lambda-expressions.aspx
- // process.OutputDataReceived += (sender, e) =>
- // {
- // using (StreamReader output = process.StandardOutput)
- // {
- // string data = output.ReadToEnd();
- // processOutput.Append(data);
- // }
- // };
// Start the process.
process.Start();
// Start the asynchronous read of the output stream.
+ // What is going to do Mono with this method? I guess, it will begin to read from the piped stream
+ // line by line and it will call to my DataReceivedEventHandler delegate implementation for every line
+ // (by means of some new thread in an asynchronous way)
process.BeginOutputReadLine();
+ // BE CAREFUL WITH DEADLOCKS (if child process fills pipes and nobody reads them, this C# parent process
+ // could wait forever because the child process would be waiting until someone reads from the pipes)
+ // In this case, the process, which should read from the stdout pipe, is this C# parent process.
+ // see: http://msdn.microsoft.com/en-us/library/vstudio/system.diagnostics.process.standardoutput
+
// Wait for the process.
process.WaitForExit();