捕获标准输出并仍然在控制台窗口中显示

6

我正在生成一个子进程,它在一个可见的控制台窗口中运行(它是运行MSBuild的批处理文件),我希望该进程生成的输出能够显示在可见的控制台窗口中,并且捕获该输出,以便我可以在代码中进行处理。我已经阅读了几个其他问题和MSDN文档,涉及到ProcessStartInfo.RedirectStandardOutput等内容,我可以从重定向的流中捕获输出并在代码中进行处理:

Process msBuild = new Process();
msBuild.StartInfo.FileName = "Build.bat";
msBuild.StartInfo.UseShellExecute = false;
msBuild.StartInfo.RedirectStandardOutput = true;
msBuild.Start();
string output = msBuild.StandardOutput.ReadToEnd();
msBuild.WaitForExit();

问题在于子进程的输出没有显示在控制台窗口中;当进程运行时,我只看到一个空白的控制台窗口在屏幕上,进程完成后窗口就消失了。
我想我可以隐藏实际的子进程窗口,并显示第二个窗口,只要捕获到输出,就将其写入该窗口,但这似乎比必要的工作还要多。是否有一种方法可以在控制台窗口中显示输出,并在完成处理时仍然捕获它?
2个回答

4

以下是我使用的内容,没有使用单独的线程:


using(System.Diagnostics.Process proc = new System.Diagnostics.Process())
{
   proc.EnableRaisingEvents = false;
   proc.StartInfo.RedirectStandardOutput = true;
   proc.StartInfo.CreateNoWindow = true;
   proc.StartInfo.UseShellExecute = false;
   proc.StartInfo.Verb = "open";
   proc.StartInfo.FileName = "XXXX";
   proc.Start();
   String sLine = "";
   while ((sLine = proc.StandardOutput.ReadLine()) != null)
   {
      System.Console.WriteLine(sLine);
   }
   proc.WaitForExit(); //Jon Skeet was here!
   errorCode = proc.ExitCode;
   proc.Close();
}

我原本以为 OP 想要保持生成进程一直运行 - 我没有注意到 WaitForExit 的调用。不过我会使用 WaitForExit 而不是你的 while 循环 - 紧密循环并不是一个好主意。 - Jon Skeet
我在努力回想一下,是否有什么原因我没有在那里使用 WaitForExit。 - crashmstr
看着我的SVN历史记录,我发现是因为我曾经使用过"while(!proc.HasExited) { /read stuff in here/ }"这样的代码,但它并没有获取到所有的文本。当我将其移出读取循环时,没有想到要改成WaitForExit。 - crashmstr

3

一旦您重定向了标准输出,它就不再指向控制台。如果要向控制台写入内容,您需要手动执行。

如果您想在进程执行时显示输出,而不是在结束时进行一次性输出,可以使用 Process 类的 "OutputDataReceived" 事件。


哇 - 我以前从没见过OutputDataReceived。很棒! - Jon Skeet
这似乎回答了一个问题,即我是否可以同时在子进程拥有的控制台窗口中显示输出并将其重定向到父进程。我的下一个问题是,是否可能不重定向输出,而只是在进程退出时从控制台捕获所有输出?如果不行,那么手动创建控制台窗口的最佳方法是什么,以便我可以在进程执行时将重定向的输出写入其中(使用“OutputDataReceived”)? - mjl5007
1
请查看http://msdn.microsoft.com/en-us/library/system.diagnostics.process.outputdatareceived.aspx。它有一个示例(您可能需要关闭除C#之外的所有语言)。 - Shea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接