C#:逐行获取外部shell命令结果

时间:2011-08-19 12:35:21

标签: c# shell process command

我正在编写一个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.

4 个答案:

答案 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();