我正在编写一个C#winform应用程序,它启动第二个进程来执行shell命令,如“dir”和“ping”。我重定向第二个进程的输出,以便我的应用程序可以接收命令结果。它大致工作正常。
唯一的问题是我的winform app整体接收命令行输出而不是逐行接收。例如,它必须等待外部“ping”命令完成(需要几秒或更长时间),然后立即接收整个输出(多行)。
我想要的是应用程序实时接收cmdline输出,即通过行而不是块。这可行吗?
我正在使用此代码来读取输出: 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.
答案 0 :(得分:3)
查看this msdn article中有关如何完成阅读完全异步的示例。
除此之外,我希望您的代码现在可以逐行读取,但UI没有任何时间重新绘制(缺少Application.DoEvents();更新RTFTextBox后
答案 1 :(得分:2)
而不是使用while ((result = proc.StandardOutput.ReadLine()) != null)
的循环,你应该使用:
...
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
当它们到达时,它将开始异步读取行,然后处理e.Data
处理程序中proc_DataReceived
读取的行,因为您使用BeginOutputReadline
e.Data
将是一个字符串。
答案 2 :(得分:1)
这可能很有用:
答案 3 :(得分:0)
我遇到了同样的问题,并通过以下方式解决了这个问题。我发现如果我在外部应用程序中出现错误,我使用ReadToEnd()
方法完全没有输出,所以切换到使用逐行streamreader。将切换到使用Saa提供的答案,因为这看起来是处理它的正确方法。
还找到了这个解决方案:c# coding convention public/private contexts同时提供错误处理,并对externalApp.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);
的使用提供更全面的解释
Process externalApp = new Process();
externalApp.StartInfo.FileName = config.ExternalApps + @"\location\DeleteApp.exe";
externalApp.StartInfo.Arguments = Directory.GetCurrentDirectory() + @"\..\..\..\project\argumentsForDeleteApp.xml";
externalApp.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
externalApp.StartInfo.UseShellExecute = false;
externalApp.StartInfo.RedirectStandardOutput = true;
Console.Out.WriteLine(DateTime.UtcNow.ToLocalTime().ToString() +
":###### External app: " + externalApp.StartInfo.FileName + " - START");
externalApp.Start();
using (StreamReader reader = externalApp.StandardOutput)
{
while (!reader.EndOfStream)
{
string result = reader.ReadLine();
Console.Out.WriteLine(result);
}
}
externalApp.WaitForExit();