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

And*_*ell 14 c# stdout visual-studio-2008 visual-studio output-window

目前我正从我的C#程序启动批处理文件:

System.Diagnostics.Process.Start(@"DoSomeStuff.bat");
Run Code Online (Sandbox Code Playgroud)

我希望能够做的是将该子进程的输出(stdout和stderr)重定向到Visual Studio中的Output窗口(特别是Visual C#Express 2008).

有没有办法做到这一点?

(另外:这样就不会全部缓冲,然后在子进程完成时吐出到Output窗口.)


(顺便说一句:目前我可以通过使我的程序成为"Windows应用程序"而不是"控制台应用程序"来使进程的stdout(但不是stderr)出现在"输出"窗口中.如果程序运行,这会中断在Visual Studio之外,但在我的特定情况下这是好的.)

Mar*_*k H 22

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();
Run Code Online (Sandbox Code Playgroud)

同样的想法Error,只需替换Output那些方法/属性名称.

  • 这个答案大多是正确的.它缺少一些东西.特别是:之后在`Begin ... ReadLine`和`WaitForExit`之前调用`Start`.另外将`RedirectStandardInput`设置为true修复了由批处理文件中的某个程序(特别是plink)引起的问题,即使它没有使用它也需要有效的stdin. (6认同)

Uwe*_*ayr 8

这个的变化对我有用 - 现在发布这个因为我希望我早些发现它.请注意,这只是从实际代码中提取的片段,因此可能存在微不足道的错误.

该技术基于一些MSDN代码.我无法弄清楚的是如何让输出窗口"动态"更新.直到此任务返回后才会更新.

// 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();
}
Run Code Online (Sandbox Code Playgroud)