Redirect but also display process output stream

2019-01-28 03:31发布

问题:

I am running a build, and I would like to be able to view the progress as it happens. But I would also like to save the output if the build has an error.

I know I can use Process.UseShellExecute = false, and RedirectStandardOutput, but that's only part of the story.

How can I do this?

回答1:

Update

As Greg mentions in the comments below, MSBuild can write out to a log file while also outputting to console out of the box.

MSBuild [options] /filelogger /fileloggerparameters:LogFile=MSBuildLog.txt

Try the following simple C# program. It will take the redirected STDIN (Console.In) and write it to one or more files and STDOUT (Console.Out).

using System;
using System.Collections.Generic;
using System.IO;

namespace RedirectToFile
{
    class Program
    {
        static void Main(string[] args)
        {
            var buffer = new char[100];
            var outputs = new List<TextWriter>();

            foreach (var file in args)
                outputs.Add(new StreamWriter(file));

            outputs.Add(Console.Out);

            int bytesRead;
            do
            {
                bytesRead = Console.In.ReadBlock(buffer, 0, buffer.Length);
                outputs.ForEach(o => o.Write(buffer, 0, bytesRead));
            } while (bytesRead == buffer.Length);

            outputs.ForEach(o => o.Close());
        }
    }
}

I use it to redirect the output from an MSBuild batch file to disk whilst still outputting to the console window.

Usage: MSBuild [options] | RedirectToFile.exe MSBuildLog.txt


回答2:

Maybe like this?

class Tee
{
    private readonly string m_programPath;
    private readonly string m_logPath;
    private TextWriter m_writer;

    public Tee(string programPath, string logPath)
    {
        m_programPath = programPath;
        m_logPath = logPath;
    }

    public void Run()
    {
        using (m_writer = new StreamWriter(m_logPath))
        {

            var process =
                new Process
                {
                    StartInfo =
                        new ProcessStartInfo(m_programPath)
                        { RedirectStandardOutput = true, UseShellExecute = false }
                };

            process.OutputDataReceived += OutputDataReceived;

            process.Start();
            process.BeginOutputReadLine();
            process.WaitForExit();
        }
    }

    private void OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        Console.WriteLine(e.Data);
        m_writer.WriteLine(e.Data);
    }
}


回答3:

this answer should help you Redirect Standard Output Efficiently in .NET

PS I am never sure if linking to another answer on SO is an answer or a comment