C# 捕获 python.exe 输出并在文本框中显示

1 投票
4 回答
5012 浏览
提问于 2025-04-16 17:27

我在这个问题上研究了一段时间。我可以很好地捕捉到控制台窗口的输出(实时),但是我无法实时捕捉到一个Python控制台应用程序的输出。我可以在Python程序运行结束后捕捉到它的输出,但我并不想要那样的结果。

我正在使用系统诊断中的进程,并且有一个后台工作者。我只是想把Python 2.6的输出捕捉到一个文本框里。我已经用其他自定义应用程序测试过我的程序,它确实可以实时显示输出。

请帮帮我

谢谢

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);
        }
    }

4 个回答

0

我记得之前也遇到过类似的问题,我在我的.py脚本里做了点类似的事情,而不是用print这个函数:

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

不过我不太确定我把shell这个参数设置成了True还是False。还有那些“std”参数我也不太确定。你可能需要在这方面多试试。

1

我在制作一个MiniConsole的时候遇到了这个问题,正是为了这个目的。

我使用了你的方法,代码如下:

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

奇怪的是,所有的输出都是从ErrorDataReceived而不是OutputDataReceived那里来的(而且我输入的命令都是有效的)。

所以我觉得你可能漏掉了:

pro.BeginErrorReadLine();

另外,我是在主线程中启动这个进程的(我没有使用任何工作线程),使用的是python27。

以下是完整的启动代码:

        // 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();
        }
2

我最近也遇到了这个问题,经过很多尝试,发现用“-u”这个选项来运行python程序效果很好。这个选项的作用是让输出不经过缓冲,这样一来,所有的东西都正常运行了。

撰写回答