简体   繁体   English

将子进程的输出(stdout,stderr)重定向到Visual Studio中的“输出”窗口

[英]Redirect the output (stdout, stderr) of a child process to the Output window in Visual Studio

At the moment I am starting a batch file from my C# program with: 目前我正从我的C#程序启动批处理文件:

System.Diagnostics.Process.Start(@"DoSomeStuff.bat");

What I would like to be able to do is redirect the output (stdout and stderr) of that child process to the Output window in Visual Studio (specifically Visual C# Express 2008). 我希望能够做的是将该子进程的输出(stdout和stderr)重定向到Visual Studio中的Output窗口(特别是Visual C#Express 2008)。

Is there a way to do that? 有没有办法做到这一点?

(Additionally: such that it's not all buffered up and then spat out to the Output window when the child process finishes.) (另外:这样就不会全部缓冲,然后在子进程完成时吐出到Output窗口。)


(BTW: At the moment I can get stdout (but not stderr) of the parent process to appear in the Output window, by making my program a "Windows Application" instead of a "Console Application". This breaks if the program is run outside Visual Studio, but this is ok in my particular case.) (顺便说一句:目前我可以通过使我的程序成为“Windows应用程序”而不是“控制台应用程序”来使进程的stdout(但不是stderr)出现在“输出”窗口中。如果程序运行,这会中断在Visual Studio之外,但在我的特定情况下这是好的。)

process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);
process.Start();
process.BeginOutputReadLine();

process.WaitForExit();

Same idea for Error , just replace Output in those method/property names. 同样的想法是Error ,只需在这些方法/属性名称中替换Output

A variation of this works for me --posting this now because I wish I'd found it earlier. 这个的变化对我有用 - 现在发布这个因为我希望我早些发现它。 Note that this is just a fragment extracted from the real code so there may be trivial errors. 请注意,这只是从实际代码中提取的片段,因此可能存在微不足道的错误。

The technique is based on some MSDN code. 该技术基于一些MSDN代码。 What I haven't been able to figure out is how to get the output window to update "on the fly". 我无法弄清楚的是如何让输出窗口“动态”更新。 It doesn't update until after this task returns. 直到此任务返回后才会更新。

// Set this to your output window Pane
private EnvDTE.OutputWindowPane _OutputPane = null;

// Methods to receive standard output and standard error

private static void StandardOutputReceiver(object sendingProcess, DataReceivedEventArgs outLine)
{
   // Receives the child process' standard output
   if (! string.IsNullOrEmpty(outLine.Data)) {
       if (_OutputPane != null)
           _OutputPane.Write(outLine.Data + Environment.NewLine);
   }
}

private static void StandardErrorReceiver(object sendingProcess, DataReceivedEventArgs errLine)
{
   // Receives the child process' standard error
   if (! string.IsNullOrEmpty(errLine.Data)) {
       if (_OutputPane != null)
           _OutputPane.Write("Error> " + errLine.Data + Environment.NewLine);
   }
}

// main code fragment
{
    // Start the new process
    ProcessStartInfo startInfo = new ProcessStartInfo(PROGRAM.EXE);
    startInfo.Arguments = COMMANDLINE;
    startInfo.WorkingDirectory = srcDir;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardError = true;
    startInfo.CreateNoWindow = true;
    Process p = Process.Start(startInfo);
    p.OutputDataReceived += new DataReceivedEventHandler(StandardOutputReceiver);
    p.BeginOutputReadLine();
    p.ErrorDataReceived += new DataReceivedEventHandler(StandardErrorReceiver);
    p.BeginErrorReadLine();
    bool completed = p.WaitForExit(20000);
    if (!completed)
    {
        // do something here if it didn't finish in 20 seconds
    }
    p.Close();
}

What's going on here is that Visual Studio is displaying the debug output from the program in the Output Window. 这里发生的是Visual Studio在输出窗口中显示程序的调试输出。 That is: if you use Trace.WriteLine, it'll appear in the Output Window, because of the default trace listener. 即:如果使用Trace.WriteLine,它将出现在输出窗口中,因为默认的跟踪侦听器。

Somehow, your Windows Form application (when it uses Console.WriteLine; I'm assuming you're using Console.WriteLine) is also writing debug output, and Visual Studio is picking this up. 不知何故,你的Windows窗体应用程序(当它使用Console.WriteLine;我假设你正在使用Console.WriteLine)也在编写调试输出,而Visual Studio正在选择它。

It won't do the same for child processes, unless you explicitly capture the output and redirect it along with your output. 它不会对子进程执行相同的操作,除非您明确捕获输出并将其与输出一起重定向。

Have you considered using a DefaultTraceListener ? 您是否考虑过使用DefaultTraceListener

    //Create and add a new default trace listener.
    DefaultTraceListener defaultListener;
    defaultListener = new DefaultTraceListener();
    Trace.Listeners.Add(defaultListener);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM