猿问

如何在.NET中生成进程并捕获其STDOUT?

如何在.NET中生成进程并捕获其STDOUT?

我需要生成一个作为控制台应用程序的子进程,并捕获它的输出。

我为一个方法编写了以下代码:

string retMessage = String.Empty;ProcessStartInfo startInfo = new ProcessStartInfo();Process p = new Process();
startInfo.CreateNoWindow = true;startInfo.RedirectStandardOutput = true;startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;startInfo.Arguments = command;startInfo.FileName = exec;p.StartInfo = startInfo
;p.Start();p.OutputDataReceived += new DataReceivedEventHandler(
    delegate(object sender, DataReceivedEventArgs e)
    {
        using (StreamReader output = p.StandardOutput)
        {
            retMessage = output.ReadToEnd();
        }
    });p.WaitForExit();return retMessage;

然而,这不会返回任何东西。我不相信OutputDataReceived事件正在被回调,或者WaitForExit()命令可能阻塞线程,因此它将永远不会回调。

有什么建议吗?

编辑:看来我对回调太费劲了。做:

return p.StandardOutput.ReadToEnd();

似乎运转良好。


撒科打诨
浏览 545回答 3
3回答

侃侃尔雅

这是我验证过的代码。我使用它来生成MSBuild并监听它的输出:process.StartInfo.UseShellExecute = false;process.StartInfo.RedirectStandardOutput = true;process.OutputDataReceived += (sender, args) => Console.WriteLine("received output: {0}", args.Data);process.Start();process.BeginOutputReadLine();

倚天杖

我需要捕获stdout和stderr,如果进程没有在预期的情况下退出,则需要超时。我想出了这个:Process process = new Process();StringBuilder outputStringBuilder = new StringBuilder();try{process.StartInfo.FileName = exeFileName;process.StartInfo.WorkingDirectory = args.ExeDirectory;process.StartInfo.Arguments = args;process.StartInfo.RedirectStandardError = true;process.StartInfo.RedirectStandardOutput = true;process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;process.StartInfo.CreateNoWindow = true;process.StartInfo.UseShellExecute = false;process.EnableRaisingEvents = false;process.OutputDataReceived += (sender, eventArgs) => outputStringBuilder.AppendLine(eventArgs.Data);process.ErrorDataReceived += (sender, eventArgs) => outputStringBuilder.AppendLine(eventArgs.Data);process.Start();process.BeginOutputReadLine();process.BeginErrorReadLine();var processExited = process.WaitForExit(PROCESS_TIMEOUT);if (processExited == false) // we timed out...{    process.Kill();    throw new Exception("ERROR: Process took too long to finish");}else if (process.ExitCode != 0){    var output = outputStringBuilder.ToString();    var prefixMessage = "";    throw new Exception("Process exited with non-zero exit code of: " + process.ExitCode + Environment.NewLine +     "Output from process: " + outputStringBuilder.ToString());}}finally{                process.Close();}我正在将stdout和stderr连接到相同的字符串中,但是如果需要的话,您可以将它分开。它使用事件,所以它应该处理它们的到来(我相信)。我已经成功地运行了这个程序,并将很快进行卷测试。
随时随地看视频慕课网APP
我要回答