2012-04-27 62 views
2

我正在尝试编写一个运行Perl脚本并读取并使用标准输出的VB .NET程序。我希望能够在打印时分别处理每一行,并相应地更新我的程序显示。下面是一些代码,我已经“写”(读:“主要是复制了互联网”):如何实时处理辅助过程的输出?

Private WithEvents pscript As Process 

Private Sub myProgram_Load(sender As Object, e As System.EventArgs) Handles Me.Load 
    pscript = New Process() 
    pscript.StartInfo.CreateNoWindow = True 
    pscript.StartInfo.FileName = "C:\perl64\bin\perl.exe" 
    pscript.StartInfo.Arguments = "C:\test.pl" 
    pscript.StartInfo.UseShellExecute = False 
    pscript.StartInfo.RedirectStandardOutput = True 
    pscript.StartInfo.RedirectStandardInput = True 
    AddHandler pscript.OutputDataReceived, AddressOf pscript_output_process 
    pscript.Start() 
    pscript.BeginOutputReadLine() 
End Sub 

Private Sub pscript_output_process(sender As Object, e As DataReceivedEventArgs) 
    MessageBox.Show(e.Data) 
End Sub 

这适用于一个问题:程序等待,直到测试脚本运行完毕,然后触发几个OutputDataReceived事件一个接一个。这意味着,当我使用真正的脚本时,它可能会在几个小时内不做任何事情,然后不得不一次处理5000个事件,尽管事实上是以相当规律的间隔印刷在那段时间。

有没有什么办法可以让它在处理每行文本时写入文本,而不是一次处理所有文本?

+0

重定向标准输出。 – dubvfan87 2012-04-27 22:51:48

+0

这可能既不存在也不存在,但帮助文档反复说明:“正在处理异步输出的应用程序应该调用WaitForExit方法以确保输出缓冲区已被刷新” – 2012-04-27 23:50:07

+0

Jim:对WaitForExit的调用会导致应用程序完全冻结,直到脚本完成,否则它以同样的方式工作。 – gorcq 2012-04-28 00:28:02

回答

0
While (pscript.HasExited = False) 
    Dim sLine As String = pscript.StandardOutput.ReadLine 
End While 
+0

出于某种原因,这只会捕获打印的第一行,并且仍然等待脚本完成。此外,它会导致我的程序在脚本运行时冻结,这就是为什么我喜欢基于事件的方法(如果它工作正常!)。 – gorcq 2012-04-28 00:35:24

1

我想通过从互联网上复制更多的东西来解决这个问题。问题似乎在Perl中,通常在每个打印语句后都不会刷新标准输出。我不知道最后一句的含义是什么,但无论如何,将local $| = 1;行添加到脚本的顶部(根据我读的网站,它会自动刷新标准输出),从而解决了这个问题。

+0

“冲洗标准输出”有点草率。它应该说“刷新STDOUT的缓冲区”。为了提高效率,默认使用快速RAM缓冲区;仅当缓冲区已满或手动清空(“刷新”)时才会将数据放入流(文件,终端,套接字)中。设置['| |'](http://p3rl.org/var#%24%7c)将关闭缓冲。 (我的解释有点不准确,但要点是真实的;这里没有足够的空间来提及更精细的细节。)阅读[患有缓冲?](http://perl.plover.com/FAQs/Buffering.html)一个扩展的讨论。 – daxim 2012-04-28 11:57:27

+0

谢谢你的文章。这使得现在更有意义。 – gorcq 2012-04-28 19:23:12