Anirudh Goel
Anirudh Goel

Reputation: 4711

Partially read standard output of another process created from c# application

I have a GUI application within which i'm spawning a console application using Process class.

Process p1 = new Process();
p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p1.StartInfo.CreateNoWindow = true;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe");
p1.StartInfo.Arguments = "/pn abc.exe /f \"temp1.txt\"";
p1.StartInfo.RedirectStandardError = true;
p1.StartInfo.RedirectStandardInput = true;
p1.StartInfo.RedirectStandardOutput = true;
p1.OutputDataReceived += new DataReceivedEventHandler(outputreceived);
p1.ErrorDataReceived += new DataReceivedEventHandler(errorreceived);
p1.Start();
tocmd = p1.StandardInput;
p1.BeginOutputReadLine();
p1.BeginErrorReadLine();

Now i have a problem that, though it reads the console output asynchronously but it seems to fire the event only when the internal buffer is filled with some amount. I want it to display data as it comes. If there's 10 bytes in buffer, let it display the 10 bytes. My program implements sleep() call internally, so i need to print the data till it goes to sleep.

How can i do it?

=============

As it was mentioned the output is line buffered, i tried the following change in the code

p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p1.StartInfo.CreateNoWindow = true;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe");
p1.StartInfo.Arguments = pnswitch + " /f \"temp1.txt\"";
p1.StartInfo.RedirectStandardError = false;
p1.StartInfo.RedirectStandardInput = true;
p1.StartInfo.RedirectStandardOutput = true;
p1.Start();
tocmd = p1.StandardInput;
MethodInvoker mi = new MethodInvoker(readout);
mi.BeginInvoke(null, p1);

and inside readout i wrote

void readout()
    {
        string str;
        while ((str = p1.StandardOutput.ReadLine()) != null)
        {
            richTextBox1.Invoke(new UpdateOutputCallback(this.updateoutput), new object[] { str });
            p1.StandardOutput.BaseStream.Flush();
        }
    }

So i think it now monitors when each line is written and it prints it right? this too didn't work. Any thing wrong there?

Upvotes: 1

Views: 4945

Answers (2)

Bogdan Maxim
Bogdan Maxim

Reputation: 5946

In order to achieve this, you must use synchronous read operations on a redirected stream. Your code would look like this (MSDN Sample):

// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
**string output = p.StandardOutput.ReadToEnd();**
p.WaitForExit();

In order to achieve async behavior you would have to use some threads.

MSDN Article here

Upvotes: 1

leppie
leppie

Reputation: 117220

The Output and Error Data received is line buffered, and will only fire when a newline is added.

Your best bet is to use you own reader that can read the input, byte by byte. Obvioulsly, this would have to be non-blocking :)

Upvotes: 3

Related Questions