C# 进程换行,某些输出不显示
我有一个小型包装应用程序,为现有控制台应用程序提供GUI。我正在使用C# 进程换行,某些输出不显示,c#,process,C#,Process,我有一个小型包装应用程序,为现有控制台应用程序提供GUI。我正在使用ProcessStartInfo和Process类绑定到.exe,然后使用BeginErrorReadLine()和BeginOutputReadLine()将任何消息重定向到新的GUI中。除了控制台调用console.Write()而不是console.WriteLine(),在这种情况下,传递给Write的文本根本不显示之外,其他一切都正常。我认为问题是因为WriteLine函数在文本后插入了换行符,而Write方法没有。有
ProcessStartInfo
和Process
类绑定到.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();
}));
}
您遇到的问题是,设置
进程
类是为了方便地对进程的输出进行面向行的基于事件的处理。如果需要在输出部分行时读取这些行,则不能使用此功能
然而,如果您需要对输出进行比面向行的工具更细粒度的控制,那么过程
类确实为您提供了所需的工具。如果重定向输出,则Process.StandardOutput
是一个StreamReader
,您可以使用整个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
它产生以下输出:
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”
是在行的其余部分前一秒读取的
但是,如果您喜欢进程
已经提供的面向事件的I/O,则这并不方便。您可以:
- 使用异步
API流
- 使用执行阻塞读取的线程
“?”
结尾的提示。这取决于你的情况
关键是,如果您想要的不是面向行的I/O,那么必须使用
StandardOutput
和StandardError
StreamReader
属性。Sladkey据我所知,使用异步和同步读取之间的问题是,我必须手动调用写入函数,而不是基于事件。这是正确的吗?最好的解决方案是类似计时器的东西吗?解析程序的输出需要编写一个解析器,最好是一个简单的解析器。将解析器作为线程编写是最容易的,否则您将需要一个状态机。如果输出是确定性的,您甚至不需要任何计时器。这不是一项琐碎的任务,解决方案取决于您的需求和应用程序。设计需要与解析线程协作,这可能是使用事件最容易做到的。除此之外,还有许多实用的方法!