Как мне вызвать Perl-скрипт в приложении C #? - PullRequest
6 голосов
/ 16 марта 2009

Я хочу записать вывод программы Perl и отобразить выходные данные (строку на экране) в текстовом поле в C # Windows Form.

Вот мой основной код 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";
    }
}

и код для 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);
}

У меня проблема в том, что выходные данные отображаются только в текстовом поле, пока не закончится Perl.

Более интересно, когда я обнаружил, что, если я делаю то же самое с консольным приложением (C #), все кажется нормальным.

Вот код для консольного приложения:

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

Я пытаюсь выяснить, что происходит с моим приложением, но все еще не могу найти подсказку. Еще одна вещь, что я не могу получить предупреждающее сообщение с приложением формы Windows.

Ответы [ 2 ]

7 голосов
/ 02 августа 2009

Вам нужно будет использовать несколько потоков, чтобы он не прерывал ваш пользовательский интерфейс. У меня довольно большой служебный класс, который запускает процессы в своем собственном потоке и передает их делегированным событиям.

Извините, я бы привел пример, но на самом деле я в огромном порыве. Но есть еще одна вещь, на которую вы должны обращать внимание при использовании сценариев Perl, - это то, что они не очищают вывод автоматически Вам необходимо поставить:

local $| = 1;

В верхней части скрипта, который вы запускаете, он автоматически сбрасывается.

2 голосов
/ 16 марта 2009

Сначала вы должны обновить обработчик события

    void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)    
    {        
         if (txtOutput.InvokeRequired)        
         {            
               UpdateUIDelegate updateDelegate = new UpdateUIDelegate 

                 (UpdateUI);this.Invoke(updateDelegate, e.Data);        
          }
          else UpdateUI(e.Data);

     }

и добавьте эту строку в btnRun_Click

proc.WaitForExit();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...