【问题标题】:C#: get external shell command result line by lineC#:逐行获取外部shell命令结果
【发布时间】:2011-10-30 14:26:12
【问题描述】:

我正在编写一个 C# winform 应用程序,它启动第二个进程来执行 shell 命令,如“dir”和“ping”。我重定向第二个进程的输出,以便我的应用程序可以接收命令结果。它大致工作正常。

唯一的问题是我的 winform 应用程序将命令行输出作为一个整体而不是逐行接收。例如,它必须等待外部“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.

【问题讨论】:

标签: c# shell process command


【解决方案1】:

查看this msdn article 中的示例,了解如何完全异步读取。

除此之外,我希望您的代码现在可以逐行读取,但 UI 没有时间重新绘制(缺少 Application.DoEvents(); 更新 RTFTextBox 后

【讨论】:

【解决方案2】:

你应该使用while ((result = proc.StandardOutput.ReadLine()) != null)而不是循环:

...
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();

这将在行到达时开始异步读取行,然后您在proc_DataReceived 处理程序中处理e.Data 读取的行,因为您使用BeginOutputReadline e.Data 将是一个字符串行。

【讨论】:

    【解决方案3】:
    【解决方案4】:

    我遇到了同样的问题,并通过以下方式解决了这个问题。我发现如果我在外部应用程序中出现错误,我使用ReadToEnd() 方法根本没有得到任何输出,因此切换到逐行使用流读取器。将切换到使用 Saa'd 提供的答案,因为这看起来是处理它的正确方法。

    还找到了这个解决方案: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();
    

    【讨论】:

      猜你喜欢
      • 2013-12-28
      • 1970-01-01
      • 2013-05-09
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多