我正在编写一个C#应用程序,它可以启动第三方命令行可执行文件并将其标准输出重定向到RichTextBox。
我可以通过使用process.OutputDataReceived事件来重定向输出。我有一个将行压入的队列,然后使用计时器将所有排队的行定期转储到RichTextBox中。
这非常适合某些第三方程序。
问题出在程序多次写入控制台的一行中。例如:5%-> 10%-> 25%等...(不断重写相同的位置)我想这是通过不放置换行符,而是简单地使用a返回到行的开头来完成的。回车并覆盖先前的字符。
发生的是,OutputDataReceived似乎没有任何指示是否应应用新行的方法,因此我的RichTextBox输出仅在新行上进行了多次更新。例如:5%10%25%等...
有什么办法可以判断标准输出是在新行还是在同一行?
如果我理解正确,那么您当前会看到进度更新以RichTextBox
单独的行报告给控件,而您想模拟控制台窗口的行为。即用新的行覆盖先前的输出行,而不是保留前一行并添加新的行。考虑到这一点…
在.NET类型,包括喜欢的东西TextReader
和Process
类的处理输出,可以考虑换行是任意的\r
,\n
或\r\n
。因此,即使只是使用a\r
来覆盖当前行的过程也将被解释OutputDataReceived
为开始新行。考虑到此行为在.NET中的一致性,您唯一的选择是避免使用任何内置的基于行的I / O机制。
幸运的是,您可以直接通过从流程中进行异步读取StandardOutput
,而不必处理基于行的OutputDataReceived
事件。例如:
async Task ConsumeOutput(TextReader reader, Action<string> callback)
{
char[] buffer = new char[256];
int cch;
while ((cch = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
callback(new string(buffer, 0, cch));
}
}
您可以这样称呼它:
// don't "await", but do keep "task" so that at some later time, you can
// check the result, "await" it, whatever, to determine the outcome.
Task task = ConsumeOutput(process.StandardOutput, s =>
{
richTextBox1.AppendText(s);
});
当然,无需进行任何修改,上面的操作就可以完成您已经拥有的功能。但是以这种方式读取输出不会对换行符产生任何解释。相反,它们将出现在s
传递给处理每个读取回调的匿名方法的字符串中。因此,您可以自己扫描该字符串,以查找表明您正在开始新行的单独回车,但是应在添加新文本之前删除前一行。在添加新文本之前,请确保首先添加(或至少跳过)回车符之前的所有文本,然后删除最后一行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句