I want to capture output of a Perl program and display output data (string on screen) in a text box on C# Windows Form.
我希望捕获Perl程序的输出,并在c# Windows窗体上的文本框中显示输出数据(屏幕上的字符串)。
Here is my main C# code:
这是我的主要c#代码:
public partial class frmMain : Form
{
private Process myProcess = null;
public frmMain()
{
InitializeComponent();
}
public delegate void UpdateUIDelegate(string data);
private void btnRun_Click(object sender, EventArgs e)
{
myProcess = new Process();
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo("perl.exe");
myProcessStartInfo.Arguments = "test.pl";
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
myProcessStartInfo.CreateNoWindow = true;
myProcess.StartInfo = myProcessStartInfo;
myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.Start();
myProcess.BeginOutputReadLine();
}
void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (txtOutput.InvokeRequired)
{
UpdateUIDelegate updateDelegate = new UpdateUIDelegate(UpdateUI);
this.Invoke(updateDelegate, e.Data);
}
}
void UpdateUI(string data)
{
txtOutput.Text += data + "\r\n";
}
}
and code for test.pl:
test.pl和代码:
my @a = qw{1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19};
my @b = qw{a b c d e f g h i j k l m n o p q r s };
print 'start' . "\n";
while ( my ( $item1, $item2) = ( splice (@a, 0, 1), splice (@b, 0, 1) ) ) {
print 'Item 1: ' . $item1 . "\n";
print 'Item 2: ' . $item2 . "\n";
warn 'Finish one item' . "\n";
sleep(1);
}
I have a problem is that the output data is only displayed on text box until the Perl has finished.
我有一个问题,输出数据只显示在文本框中,直到Perl完成。
It's more interesting when I found that, If I do the same with a console application (C#) everything seems okay.
当我发现,如果我用一个控制台应用程序(c#)做同样的事情,一切看起来都很好,那就更有趣了。
Here's the code for console application:
下面是控制台应用程序的代码:
class Program
{
static void Main(string[] args)
{
Process myProcess = new Process();
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo("perl.exe");
myProcessStartInfo.Arguments = "test.pl";
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcess.StartInfo = myProcessStartInfo;
myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.Start();
myProcess.BeginOutputReadLine();
Console.Read();
}
static void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}
}
I'm trying to figure out what happens with my form application but still not find any clue. One more thing is that I can not get warn message with windows form application.
我想知道我的表单应用程序会发生什么,但仍然没有找到任何线索。还有一件事是,我不能通过windows窗体应用程序得到警告消息。
2 个解决方案
#1
7
You're going to need to use multiple threads so it doesn't interupt your UI. I have a fairly large utility class that launches processes on its own thread and pipes to delegated events.
您将需要使用多个线程,因此它不会影响您的UI。我有一个相当大的实用程序类,它在自己的线程和管道上启动进程,以委派事件。
Sorry, I'd give an example but I'm actually in a huge rush. But one thing else you will want to watch out for with using Perl scripts is that they do not auto flush the output nicely. You need to put:
不好意思,我想举个例子,但我真的很着急。但是,您还需要注意的一点是,使用Perl脚本时,它们不能很好地自动刷新输出。你需要把:
local $| = 1;
At the top of your script that you're running so it auto flushes.
在你的脚本顶部,你正在运行,所以它自动刷新。
#2
2
First you have to update the event handler
首先需要更新事件处理程序。
void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (txtOutput.InvokeRequired)
{
UpdateUIDelegate updateDelegate = new UpdateUIDelegate
(UpdateUI);this.Invoke(updateDelegate, e.Data);
}
else UpdateUI(e.Data);
}
and add this line in your btnRun_Click
并在btnRun_Click中添加这一行。
proc.WaitForExit();
#1
7
You're going to need to use multiple threads so it doesn't interupt your UI. I have a fairly large utility class that launches processes on its own thread and pipes to delegated events.
您将需要使用多个线程,因此它不会影响您的UI。我有一个相当大的实用程序类,它在自己的线程和管道上启动进程,以委派事件。
Sorry, I'd give an example but I'm actually in a huge rush. But one thing else you will want to watch out for with using Perl scripts is that they do not auto flush the output nicely. You need to put:
不好意思,我想举个例子,但我真的很着急。但是,您还需要注意的一点是,使用Perl脚本时,它们不能很好地自动刷新输出。你需要把:
local $| = 1;
At the top of your script that you're running so it auto flushes.
在你的脚本顶部,你正在运行,所以它自动刷新。
#2
2
First you have to update the event handler
首先需要更新事件处理程序。
void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (txtOutput.InvokeRequired)
{
UpdateUIDelegate updateDelegate = new UpdateUIDelegate
(UpdateUI);this.Invoke(updateDelegate, e.Data);
}
else UpdateUI(e.Data);
}
and add this line in your btnRun_Click
并在btnRun_Click中添加这一行。
proc.WaitForExit();