2009-03-16 22 views
6

Tôi muốn chụp đầu ra của một chương trình Perl và hiển thị dữ liệu đầu ra (chuỗi trên màn hình) trong một hộp văn bản trên C# Windows Form.Làm thế nào để gọi kịch bản Perl trong ứng dụng C#?

Đây là chính mã của tôi 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"; 
    } 
} 

và mã cho 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); 
} 

Tôi có một vấn đề là các dữ liệu đầu ra chỉ được hiển thị trên hộp văn bản cho đến khi Perl Đã hoàn thành xong.

Điều thú vị hơn khi tôi thấy rằng, Nếu tôi làm tương tự với một ứng dụng giao diện điều khiển (C#) mọi thứ có vẻ ổn.

Dưới đây là đoạn code cho các ứng dụng giao diện điều khiển:

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

Tôi đang cố gắng để tìm ra những gì xảy ra với ứng dụng hình thức của tôi, nhưng vẫn không tìm thấy bất kỳ manh mối. Một điều nữa là tôi không thể nhận được thông báo cảnh báo bằng ứng dụng biểu mẫu cửa sổ.

+0

Xin chào! Minh, tôi đang sử dụng mã trên để chạy tệp perl cục bộ và nhận thời gian chạy trong hộp văn bản như mong đợi nhưng khi tôi chạy tệp bat máy từ xa từ tệp batch machine.then cục bộ được truy xuất trong máy từ xa nhưng đầu ra không hiển thị trong hộp văn bản. i m chỉ sửa đổi 2 dòng này từ mã trên 'ProcessStartInfo myProcessStartInfo = new ProcessStartInfo (" psexec.exe "); myProcessStartInfo.Arguments = "\\ \\\ machinename -u Miền \\ usr -p vượt qua C: \\ run.bat"; ' xin hãy giúp tôi. – picnic4u

+0

Bạn đã thử chạy lệnh trong Command Prompt chưa? nếu có, nó đã sản xuất những gì bạn mong đợi? –

+0

có, cùng một lệnh 'psexec \\ machinename -u Miền \ usr -p pass c: \ run.bat' đang làm việc từ dấu nhắc lệnh và cho đầu ra như mong đợi trong dấu nhắc lệnh. – picnic4u

Trả lời

7

Bạn sẽ cần phải sử dụng nhiều luồng vì vậy nó không ngắt của bạn Giao diện người dùng. Tôi có một lớp tiện ích khá lớn để khởi chạy các quy trình trên luồng và đường ống riêng của mình cho các sự kiện được ủy quyền.

Xin lỗi, tôi đưa ra một ví dụ nhưng tôi thực sự đang rất vội vã. Nhưng một điều khác bạn sẽ muốn xem ra cho bằng cách sử dụng kịch bản Perl là họ không tự động tuôn ra đầu ra độc đáo. Bạn cần phải đặt:

local $| = 1; 

Ở đầu tập lệnh bạn đang chạy để nó tự động tuôn ra.

+0

Cảm ơn bạn, Nó hoạt động giống như ma thuật :) –

2

Trước tiên, bạn phải cập nhật các xử lý sự kiện

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

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

    } 

và thêm dòng này trong thư mục btnRun_Click

proc.WaitForExit(); 
+0

Đầu tiên, gọi proc.WaitFroExit(); làm cho thread chính (UI Thread) đợi cho đến khi chương trình Perl kết thúc. Tôi không muốn điều đó. Tôi muốn chương trình phản ứng nhanh hơn. Trong thực tế, chương trình perl sẽ chạy trong vài giờ. –

Các vấn đề liên quan