1

I have worked on this issue for a while. I can capture the output(live) of the console window just fine, but I can't capture the output of a python console application in real time. I can capture the output of the python program after it has finished running, but i don't want that. I am using process from system.diagonistics. with a background worker. I simply want to capture the python26 output onto a text box. I have tested my program with other custom applications, and it does display the output(live).

Help please

Thanks

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace ProcessDisplayoutput
{
public partial class Form1 : Form
{

    //Delegates

    delegate void AppendTextDelegate(string text);

    public Form1()
    {
        InitializeComponent();
        Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);

    }

    private void StartButton_Click(object sender, EventArgs e)
    {
        ResultTextBox.Clear();
        if (!Worker.IsBusy)
        {
            Worker.RunWorkerAsync();
        }
    }

    public void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Process pro = new Process();
        pro.StartInfo.RedirectStandardOutput = true;
        pro.StartInfo.RedirectStandardError = true;
        pro.StartInfo.UseShellExecute = false;
        pro.StartInfo.CreateNoWindow = true;
        pro.EnableRaisingEvents = true;
        pro.OutputDataReceived +=new DataReceivedEventHandler(OnDataReceived);
        pro.ErrorDataReceived +=new DataReceivedEventHandler(OnDataReceived);

        //Test with random program worked,
        //now need to test with python
        //*****************TEST 1: PASSED **************************
        pro.StartInfo.FileName = "C:\\TestProcessOutput.exe";
        //*****************END TEST1*******************************

        //*****************TEST 2: FAILED *************************
        //pro.StartInfo.FileName = "C:\\Python26\\python.exe";
        //pro.StartInfo.Arguments = "\"C:\\Python26\\testScript.py\"";
        //*****************END TEST2 *******************************

        StreamReader sr = null;
        try
        {
            pro.Start();

            pro.BeginOutputReadLine();
            //An alternative option to display the output with the same results
            //sr = pro.StandardOutput;
            //string line = "";
            //while ((line = sr.ReadLine()) != null)
            //{
           //     appendText(line);
           // }

        }

        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }


    public void OnDataReceived(object sender, DataReceivedEventArgs e)
    {

        if (e.Data != null)
        {
            string temp = (e.Data) + Environment.NewLine;
            appendText(temp);

        }
    }
    public void appendText(string text)
    {
        if (ResultTextBox.InvokeRequired)
        {
            ResultTextBox.Invoke(new AppendTextDelegate(appendText), new object[] { text });
        }
        else
        {
            ResultTextBox.AppendText(text);
        }
    }
AshitakaLax
  • 11
  • 1
  • 2
  • Have you attempted to poll the output stream rather then use the event and see if you are geting any data. The documentation refferes to calling the event every time it gets a line, however I wonder if that means \c\n or just \n – rerun May 11 '11 at 16:59
  • Ironpython textbox maybe a useful tool for your purpose http://www.codeproject.com/KB/miscctrl/irontextbox.aspx – lucemia May 11 '11 at 17:13

4 Answers4

2

I just ran into this question myself, and after a ton of experimenting, what worked for me was running the python process with the "-u" option, which makes the output unbuffered. With that, everything worked completely fine.

Vishnu Menon
  • 61
  • 1
  • 6
1

I ran into this problem while making a MiniConsole exactly for that purpose.

I used your technique with

pro.EnableRaisingEvents = true;
pro.OutputDataReceived +=new DataReceivedEventHandler(OnDataReceived);
pro.ErrorDataReceived +=new DataReceivedEventHandler(OnDataReceived);

The strange thing is that all the output was coming from ErrorDataReceived instead of OutputDataReceived (with valid commands).

So I think you're missing:

pro.BeginErrorReadLine();

Also I was starting the process in the main thread (I don't have any worker), using python27.

Here is the full start:

        // executable: "c:\\python27\\python.exe", arguments: "myscript.py"
        ProcessStartInfo startInfo = new ProcessStartInfo(executable, arguments);
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardError = true;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.WorkingDirectory = textBoxWorkingDirectory.Text;

        try
        {
            Process p = new Process();
            p.StartInfo = startInfo;
            p.EnableRaisingEvents = true;
            p.OutputDataReceived += new DataReceivedEventHandler(OnDataReceived);
            p.ErrorDataReceived += new DataReceivedEventHandler(OnDataReceived);
            p.Exited += new EventHandler(OnProcessExit);
            p.Start();
            p.BeginOutputReadLine();
            p.BeginErrorReadLine();
        }
Romz
  • 544
  • 4
  • 16
0

I remember having a similar issue a while back and I think I did something similar to this in my .py scripts instead of using the print function:

sLog = 'Hello World!'
subprocess.Popen( 'echo ' + sLog, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True )

Not sure if I set the shell parameter to True or False though. Also not sure about all the "std" parameters. You might want to experiment a bit there.

SuperOli
  • 1,784
  • 1
  • 11
  • 23
0

If you're starting the Python process from your code, then THIS will make your life really easy and I think it's about the cleanest way to go.

em70
  • 6,088
  • 6
  • 48
  • 80