处理包装,某些输出不显示

时间:2011-07-03 02:11:31

标签: c# process

我有一个小的包装应用程序,可以为现有的控制台应用程序提供GUI。我正在使用ProcessStartInfoProcess类绑定到.exe,然后使用BeginErrorReadLine()BeginOutputReadLine()将任何消息重定向到新的GUI。一切正常,除非控制台调用Console.Write()而不是Console.WriteLine(),在这种情况下,传递给Write的文本根本不会显示。我认为问题是因为WriteLine函数在文本后插入换行符,而Write方法则没有。有没有办法绕过这个?我无法在原始命令行程序中将其从Write更改为WriteLine,因为Write用于提示输入。

相关守则:

var startInfo = new ProcessStartInfo(ServerFile);
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;

ServerProc = new Process();
ServerProc.StartInfo = startInfo;
ServerProc.EnableRaisingEvents = true;
ServerProc.ErrorDataReceived += new DataReceivedEventHandler(ServerProc_ErrorDataReceived);
ServerProc.OutputDataReceived += new DataReceivedEventHandler(ServerProc_OutputDataReceived);

private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    Dispatcher.Invoke(new Action(() =>
    {
        ConsoleTextBlock.Text += e.Data + "\r\n";
        ConsoleScroll.ScrollToEnd();
    }));
}

private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Dispatcher.Invoke(new Action(() =>
    {
        ConsoleTextBlock.Text += e.Data + "\r\n";
        ConsoleScroll.ScrollToEnd();
    }));
}

1 个答案:

答案 0 :(得分:2)

您遇到的问题是Process类已设置为方便的面向行的基于事件的流程输出处理。如果需要在输出时读取部分行,则无法使用此功能。

尽管如此,如果您需要比面向行的设施更精细地控制输出,Process类确实为您提供了所需的工具。如果您重定向输出,则Process.StandardOutputStreamReader,您可以使用整个StreamReader API,而不是强制读取整行。

例如,以下是标准输出的逐字符读取:

var start = DateTime.Now;
int n;
while ((n = ServerProc.StandardOutput.Read()) != -1)
{
    var c = (char)n;
    var delta = (DateTime.Now - start).TotalMilliseconds;
    Console.WriteLine("c = {0} (0x{1:X}) delta = {2}",
        char.IsWhiteSpace(c) ? '*' : c, n, delta);
}

如果我们在另一个产生此输出的控制台程序上运行它:

Console.Write("abc");
Thread.Sleep(1000);
Console.WriteLine("def");

它产生这个输出:

c = a (0x61) delta = 44.0025
c = b (0x62) delta = 44.0025
c = c (0x63) delta = 44.0025
c = d (0x64) delta = 1109.0634
c = e (0x65) delta = 1110.0635
c = f (0x66) delta = 1110.0635
c = * (0xD) delta = 1110.0635
c = * (0xA) delta = 1110.0635

表示在行的其余部分之前读取"abc"一秒钟。

但是,如果您喜欢Process已经提供的面向事件的I / O,这是不方便的。你可以:

  • 使用异步Stream API
  • 使用阻塞读取的线程

甚至可能会推出满足您需求的基于事件的I / O.

你正在编写一个解析另一个程序面向字符的输出的程序,所以如果没有完整的行,你需要某种超时来表示“我现在已经确信程序已经完成了暂时的输出。”根据输出的可预测程度,这可能很容易或很难。例如,您可能能够识别以"?"结尾的提示。这取决于你的情况。

关键是,如果您需要除了面向行的I / O之外的其他内容,则必须使用StandardOutputStandardError StreamReader属性。