C#:逐行获取外部shell命令结果
我正在编写一个 C# winform 应用程序,它启动第二个进程来执行“dir”和“ping”等 shell 命令。我重定向第二个进程的输出,以便我的应用程序可以接收命令结果。大致工作得很好。
唯一的问题是我的 winform 应用程序接收整个命令行输出,而不是逐行接收。例如,它必须等待外部“ping”命令完成(这需要很多秒或更长时间),然后立即接收整个输出(很多行)。
我想要的是应用程序实时接收命令行输出,即按行而不是按块。这可行吗?
我正在使用此代码来读取输出: while ((result = proc.StandardOutput.ReadLine()) != null)
但它没有按我预期的方式工作。 提前致谢。
编辑:这是我正在使用的代码:
System.Diagnostics.ProcessStartInfo procStartInfo = new
System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
// The following commands are needed to redirect the standard output.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result;
try {
while ((result = proc.StandardOutput.ReadLine()) != null)
{
AppendRtfText(result+"\n", Brushes.Black);
}
} // here I expect it to update the text box line by line in real time
// but it does not.
I am writing a C# winform application that starts a second process to execute shell commands like "dir" and "ping". I redirect the second process's output so my app can receive the command result. It roughly works fine.
The only problem is my winform app receives the command line output as a whole instead of line by line. For example, it has to wait for the external "ping" command to finish (which takes many seconds or longer) and then receives the whole output (many lines) at once.
What I want is the app receives the cmdline output in real-time, i.e. by lines not by block. Is this doable?
I am using this code to read the output:
while ((result = proc.StandardOutput.ReadLine()) != null)
But it does not work the way I expected.
Thanks in advance.
EDIT: here is the code I am using:
System.Diagnostics.ProcessStartInfo procStartInfo = new
System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
// The following commands are needed to redirect the standard output.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result;
try {
while ((result = proc.StandardOutput.ReadLine()) != null)
{
AppendRtfText(result+"\n", Brushes.Black);
}
} // here I expect it to update the text box line by line in real time
// but it does not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
查看这篇 msdn 文章 关于如何完全异步进行读取。
除此之外,我希望您的代码现在可以逐行读取,但 UI 没有任何时间重新绘制(缺少 Application.DoEvents(); 更新 RTFTextBox 后
Have a look at the example in this msdn article on how to do the reading completly async.
Beyond that I expect your code does to read line by line now but the UI doesn't get any time to repaint (missing Application.DoEvents(); after updating the RTFTextBox
您应该使用 while ((result = proc.StandardOutput.ReadLine()) != null) 循环,而不是使用:
这将在行到达时开始异步读取行,然后处理读取的行通过
proc_DataReceived
处理程序中的e.Data
,因为您使用BeginOutputReadline
,所以e.Data
将是字符串lines 。Instead of loop using
while ((result = proc.StandardOutput.ReadLine()) != null)
you should of using:This will start asynchronous reading the lines when they arrives, you then handle the lines read by
e.Data
inproc_DataReceived
handler, since you are useBeginOutputReadline
thee.Data
will be a string lines.这可能很有用:
http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/8d6cebfc-9b8b-4667-85b5-2b92105cd0b7/
http://www.dotnetperls.com/redirectstandardoutput
This could be usefull:
http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/8d6cebfc-9b8b-4667-85b5-2b92105cd0b7/
http://www.dotnetperls.com/redirectstandardoutput
我遇到了同样的问题并通过以下方法解决了它。我发现,如果外部应用程序出现错误,我使用 ReadToEnd() 方法根本得不到任何输出,因此改用逐行流读取器。将切换到使用 Saa'd 提供的答案,因为这看起来是处理它的正确方法。
还找到了这个解决方案: c# 编码约定公共/私有上下文 它提供了同时进行错误处理并对 externalApp.OutputDataReceived += (sender, args) => 的使用给出更全面的解释Console.WriteLine(args.Data);
I had the same issue and got around it with the following. I found that if I had an error in the external app I was getting no output at all using the
ReadToEnd()
method, so switched to use the line by line streamreader. Will be switching over to use the answer provided by Saa'd though as that looks like the proper way to handle it.Also found this solution: c# coding convention public/private contexts which provides for error handling at the same time and giving a fuller explanation to the use of
externalApp.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);