Minh Le
Minh Le

Reputation: 1165

How do I call Perl script in C# application?

I want to capture output of a Perl program and display output data (string on screen) in a text box on C# Windows Form.

Here is my main C# code:

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:

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.

It's more interesting when I found that, If I do the same with a console application (C#) everything seems okay.

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.

Upvotes: 7

Views: 17971

Answers (2)

Game_Overture
Game_Overture

Reputation: 1666

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.

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:

local $| = 1;

At the top of your script that you're running so it auto flushes.

Upvotes: 7

Ahmed
Ahmed

Reputation: 7238

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

proc.WaitForExit();

Upvotes: 2

Related Questions