C# 捕获 python.exe 输出并在文本框中显示
我在这个问题上研究了一段时间。我可以很好地捕捉到控制台窗口的输出(实时),但是我无法实时捕捉到一个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程序效果很好。这个选项的作用是让输出不经过缓冲,这样一来,所有的东西都正常运行了。