13

When I run msbuild at the command line it shows pretty colours in the console.

However when I run it from C# with Process.Start, the output appears in black and white. How can I keep the colours?

var info = new ProcessStartInfo("msbuild")
{
    UseShellExecute = false,
    CreateNoWindow = true,
    RedirectStandardError = true,
    RedirectStandardOutput = true,            
};

using (var p = Process.Start(info) )
{
    p.ErrorDataReceived += (s, e) => Console.Error.WriteLine(e.Data);
    p.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
    p.BeginErrorReadLine();
    p.BeginOutputReadLine();
    p.WaitForExit();
}

Also, while we're here, does it matter than I run Process.Start before BeginOutputReadLine ? Will any output be lost?


Motivation, for those interested. A project I work on uses a custom build tool (re-inventing the wheel imho). It uses msbuild but behind convoluted layers of indirection (simplified model above). Msbuild's helpful colours are lost. I'd like to save them.

4

4 回答 4

8
   p.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);

Process.OutputDataReceived 读取文本,而不是颜色。此下方的输出重定向功能仅重定向标准输出文本,而不是控制台颜色属性。>当您从命令行使用重定向运算符运行 msbuild 以将其输出发送到文本文件时,您会得到完全相同的结果。当您在记事本中打开文本文件时,您当然会看到平淡无奇的文本。

解析重定向的输出以重新着色您自己的输出是非常不切实际的。你被乏味困住了。再说一次,程序员不会经常抱怨 IDE 中错误列表窗口的外观:)

于 2013-07-05T16:43:54.253 回答
4

就是这样,没有其他方法可以做到这一点。您的代码首先启动该过程,然后附加事件处理程序。所以可能会有一些数据丢失,但这取决于 cpu 处理代码的速度。您最好先附加事件处理程序,然后再启动该过程。(见下文)

using (var p = new Process())
{
    p.StartInfo = new ProcessStartInfo("msbuild")
    {
        UseShellExecute = false,
        CreateNoWindow = true,
        RedirectStandardError = true,
        RedirectStandardOutput = true,
    };
    p.ErrorDataReceived += (s, e) => ErrorLine(e.Data);
    p.OutputDataReceived += (s, e) => OutputLine(e.Data);
    p.BeginErrorReadLine();
    p.BeginOutputReadLine();
    p.Start();
    p.WaitForExit();
}
void ErrorLine(string text)
{
    Console.ForegroundColor = ConsoleColor.White;
    Console.BackgroundColor = ConsoleColor.DarkRed;
    Console.Error.WriteLine(text);
    Console.ResetColor();
}
void OutputLine(string text)
{
    Console.Error.WriteLine(text);
}
于 2013-07-22T10:21:40.727 回答
1

我不知道如何针对所有警告/错误/其他具有不同颜色的东西专门针对 msbuild 执行此操作,但是您可以Console.ForegroundColor = ConsoleColor.Red;在写入之前使用更改控制台颜色,然后使用Console.ResetColor();

因此,您将更改 ErrorDataRecieved 订阅以在写入之前将颜色更改为红色,并在写入输出后重置颜色。

于 2013-07-05T16:33:19.863 回答
0

这个问题的潜在解决方案。现在可以解决这个问题,因为控制台基础结构几乎完全在 Windows 上进行了重新设计。介绍 Windows 伪控制台

使用 ConPTY 创建 MsBuild 将给出完整的 VT 输出。

 public void Start(string command, int consoleWidth = 80, int consoleHeight = 30)
    {
        using (var inputPipe = new PseudoConsolePipe())
        using (var outputPipe = new PseudoConsolePipe())
        using (var pseudoConsole = PseudoConsole.Create(inputPipe.ReadSide, outputPipe.WriteSide, consoleWidth, consoleHeight))
        using (var process = ProcessFactory.Start(command, PseudoConsole.PseudoConsoleThreadAttribute, pseudoConsole.Handle))
        {
            // copy all pseudoconsole output to a FileStream and expose it to the rest of the app
            ConsoleOutStream = new FileStream(outputPipe.ReadSide, FileAccess.Read);
            OutputReady.Invoke(this, EventArgs.Empty);

            // Store input pipe handle, and a writer for later reuse
            _consoleInputPipeWriteHandle = inputPipe.WriteSide;
            _consoleInputWriter = new StreamWriter(new FileStream(_consoleInputPipeWriteHandle, FileAccess.Write))
            {
                AutoFlush = true
            };

            // free resources in case the console is ungracefully closed (e.g. by the 'x' in the window titlebar)
            OnClose(() => DisposeResources(process, pseudoConsole, outputPipe, inputPipe, _consoleInputWriter));

            WaitForExit(process).WaitOne(Timeout.Infinite);
        }
    }

来源: https ://github.com/microsoft/terminal/blob/07d06f62aa5a883f70cbe8572bf8ea1f8577f53f/samples/ConPTY/GUIConsole/GUIConsole.ConPTY/Terminal.cs

于 2021-06-22T06:30:49.537 回答