Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I redirect process output (console) to richtextbox?

Tags:

c#

what is wrong why is that the richtextbox doesnt get the stream of Process output? theres no text display in richtextbox..

 private void button1_Click(object sender, EventArgs e)
    {

        Process sortProcess;
        sortProcess = new Process();
        sortProcess.StartInfo.FileName = "sort.exe";
        sortProcess.StartInfo.Arguments = this.comboBox1.SelectedItem.ToString();
        // Set UseShellExecute to false for redirection.
        sortProcess.StartInfo.CreateNoWindow = true;
        sortProcess.StartInfo.UseShellExecute = false;



        // Redirect the standard output of the sort command.  
        // This stream is read asynchronously using an event handler.
        sortProcess.StartInfo.RedirectStandardOutput = true;
        sortOutput = new StringBuilder("");

        // Set our event handler to asynchronously read the sort output.
        sortProcess.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);

        // Redirect standard input as well.  This stream
        // is used synchronously.
        sortProcess.StartInfo.RedirectStandardInput = true;

        // Start the process.
        sortProcess.Start();



        // Start the asynchronous read of the sort output stream.
        sortProcess.BeginOutputReadLine();
        sortProcess.WaitForExit();


        richTextBox1.AppendText(sortOutput.ToString());
    }

    private static void SortOutputHandler(object sendingProcess,
        DataReceivedEventArgs outLine)
    {
            sortOutput.Append(Environment.NewLine +
                "[" + numOutputLines.ToString() + "] - " + outLine.Data);
        }
    }

so when sort.exe launches, it displays text, i want all those text be displayed also in richtextbox in RealTime (i dont want to wait for the process to exit, and then read all output)

how can i do it? any wrong part of my code? thanks

UPDATE @botz

i added this in my code

 private void SortOutputHandler(object sendingProcess,
        DataReceivedEventArgs outLine)
    {

            sortOutput.Append(Environment.NewLine +
                "[" + numOutputLines.ToString() + "] - " + outLine.Data);
            richTextBox1.AppendText(sortOutput.ToString());


    }

but it throws this exception

Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.
like image 468
Lufthansa Avatar asked Jun 29 '11 13:06

Lufthansa


Video Answer


2 Answers

WaitForExit() blocks your UI Thread, so you don't see the new output. Either wait for the process in a separate thread or replace WaitForExit() with something like this:

while (!sortProcess.HasExited) {
     Application.DoEvents(); // This keeps your form responsive by processing events
}

In your SortOutputHandler, you can now directly append output to your textbox. But you should remember to check if you need to invoke it on the UI Thread.

You can check if it's on the UI thread this way in your handler:

    if (richTextBox1.InvokeRequired) { richTextBox1.BeginInvoke(new DataReceivedEventHandler(SortOutputHandler), new[] { sendingProcess, outLine }); }
    else {
        sortOutput.Append(Environment.NewLine + "[" + numOutputLines.ToString() + "] - " + outLine.Data);
        richTextBox1.AppendText(sortOutput.ToString());
    }
like image 196
Botz3000 Avatar answered Oct 02 '22 00:10

Botz3000


This is working for me:

private void button1_Click(object sender, EventArgs e)
    {
        using (Process sortProcess = new Process())
        {
            sortProcess.StartInfo.FileName = @"F:\echo_hello.bat";
            sortProcess.StartInfo.CreateNoWindow = true;
            sortProcess.StartInfo.UseShellExecute = false;
            sortProcess.StartInfo.RedirectStandardOutput = true;

            // Set event handler
            sortProcess.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);

            // Start the process.
            sortProcess.Start();

            // Start the asynchronous read
            sortProcess.BeginOutputReadLine();

            sortProcess.WaitForExit();
        }
    }

    void SortOutputHandler(object sender, DataReceivedEventArgs e)
    {
        Trace.WriteLine(e.Data);
        this.BeginInvoke(new MethodInvoker(() =>
        {
            richTextBox1.AppendText(e.Data ?? string.Empty);
        }));
    }

The example you started with was a console application, which doesn't care much about multithreaded access. For Windows Forms when you update a control this has to be done from the main UI thread, which is why BeginInvoke is needed. If you want to check rapidly if a handler like SortOutputHandler is working properly you can use System.Diagnostics.Trace.Write*, which doesn't need BeginInvoke.

EDIT: echo_hello.bat simply echoes the "hello" string:

@echo off
echo hello
like image 32
Sorin Comanescu Avatar answered Oct 02 '22 00:10

Sorin Comanescu