Topics

How to redirect process output to WinForm textbox in real-time?


Hailiang Shen
 

Hello all, I am trying to run a python3 script with .NET Process class. The python3 script runs slow and prints progress along the way, so I’d like to redirect the process prints to a WinFrom textbox.

 

My program includes a few threads:

Thread1 – generates a WinForm and puts it in Thread2

Thread2 – launches the python3 script in Thread3 using .NET Process class

Thread3 – redirects the process prints to a WinForm textbox (in Thread2) in real-time

 

I tried to Invoke the textbox Text update, .NET Mutex class but the process is always dumped at the end of the process but not in real-time.

 

Could you advise what else I may try? Thanks,

 

Hailiang

 


邓 君卓
 

    class StreamReceiver : StreamWriter
    {
        List<string> buffer = new List<string>();
        #region Event
        public event EventHandler<string> StringWritten;
        #endregion
 
        #region CTOR
        public StreamReceiver(Stream s) : base(s)
        { }
        #endregion
 
        #region Private Methods
        private void LaunchEvent(string txtWritten)
        {
            if (StringWritten != null)
            {
                StringWritten(this, txtWritten);
            }
        }
        #endregion
 
 
        #region Overrides
 
        public override void Write(string value)
        {
            base.Write(value);
            buffer.Add(value);
            LaunchEvent(value);
        }
        public override void Write(bool value)
        {
            base.Write(value);
            buffer.Add(value.ToString());
            LaunchEvent(value.ToString());
        }
 
        public string ReadOnce()
        {
            string pop = buffer[buffer.Count - 1];
            buffer.RemoveAt(buffer.Count - 1);
            return pop;
        }
 
        public string ReadToEnd()
        {
            StringBuilder sb = new StringBuilder();
            foreach(string str in buffer)
            {
                sb.Append(str);
            }
            buffer.Clear();
            return sb.ToString();
        }
        #endregion
    }
Then do this:
py = Python.CreateEngine();
scope = py.CreateScope();
MemoryStream ms = new MemoryStream();
output = new StreamReceiver(ms);
py.Runtime.IO.SetOutput(ms, output);
py.Runtime.IO.SetErrorOutput(ms, output);
Event StringWritten will have what you want. Update the textbox in its handler.