5

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?

3 Answers 3

3

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);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

+1. I'm sure this works, but I had trouble getting it to work, probably because I'm using a static class.
2

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

4 Comments

ReadBlock() isn't required to always return the whole buffer full. You should check for bytesRead > 0 instead.
+1 this works pretty well, (despite it being somewhat spastic about how it prints to the screen) but unfortunately the colors from msbuild are lost. Any idea how to preserve those?
Using the above program, there is no way to preserve the console output colours. If want additional logging from MSBuild have a look at the msbuild.exe /logger option, msdn.microsoft.com/en-us/library/ms171470.aspx
MSBuild can write out to a log file while also outputting to console out of the box. MSBuild [options] /filelogger /fileloggerparameters:LogFile=MSBuildLog.txt
1

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

1 Comment

good link but it doesn't quite show what I was looking for exactly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.