poldoj
poldoj

Reputation: 137

Getting line by line output from a started process

I'm trying to retrieve the output lines generated by a process I started, here's the code

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (myData singleJob in e.Argument as List<myData>)
    {
        ProcessStartInfo psi = new ProcessStartInfo("myCommandLineProgram.exe");
        psi.Arguments = "\"" + singleJob.row + "\"";
        psi.CreateNoWindow = true;
        psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;
        psi.UseShellExecute = false;
        Process p = new Process();
        p.StartInfo = psi;
        p.Start();
        StreamReader sr = p.StandardOutput ;
        string line;
        while ((line = sr.ReadLine()) != null )
        {
            this.Invoke((MethodInvoker)delegate
            {
                    richTextBox1.AppendText(sr.ReadLine() + Environment.NewLine);
                    richTextBox1.ScrollToCaret();   

            });
        }

        //StreamReader streamOutput = p.StandardOutput;
        //string content = streamOutput.ReadToEnd();   
        //this.Invoke((MethodInvoker)delegate
        //{
        //    richTextBox1.AppendText(content + Environment.NewLine);
        //});

        p.WaitForExit();
    }
}

While the commented out code is always working (but it doesn't parse line by line), the code above is somehow faulty, indeed some lines fail to appear into the richtextbox and some others are blank.

Thanks

Upvotes: 1

Views: 145

Answers (2)

MartinStettner
MartinStettner

Reputation: 29164

Shouldn't that be something like

richTextBox1.AppendText(line + Environment.NewLine);

(line instead of sr.ReadLine())?

Calling readLine() twice will discard every second line.

Also, since you're calling ReadLine in the delegate you cannot control when the read occurs. It might be that there were several ReadLines() (from the while line) in between.

Note, that you should also NOT use the line variable: This variable always references the same line variable in the loop, this one might contain new content at the time the AppendText is executed. You should introduce a new local variable inside the loop like

 while ((line = sr.ReadLine()) != null )
 {
   var theLine = line;
   this.Invoke((MethodInvoker)delegate
   {
       richTextBox1.AppendText(theLine + Environment.NewLine);
       richTextBox1.ScrollToCaret();   
   });
 }

Upvotes: 3

Nikola Davidovic
Nikola Davidovic

Reputation: 8656

Just change here instead of ReadLine(), put line. You have already read the line in your while loop

string appendingLine = line;
this.Invoke((MethodInvoker)delegate
{
          richTextBox1.AppendText(appendingLine + Environment.NewLine);
          richTextBox1.ScrollToCaret();   

});

EDIT: The answer MartinStettner gave is better one. There may be the case where line changes before the delegate is executed, therefore some lines can be lost while others can be repeated. Therefore I will change my answer according to Martin's and I want to point out that he should be the one who will take the credit for this answer.

Upvotes: 2

Related Questions