5

I'm trying to convert an existing command line tool into msbuild custom task. This tool logs messages and errors using the System.Console class.
I've added to the tool's assembly a class that inherits from Microsoft.Build.Utilities.Task and calls the tool main function, and the custom tool works fine - but no messages/errors are displayed (on the Visual Studio output window).

I would like to avoid changing the original tool's code (otherwise I could change every "Console.Error.WriteLine" to "Log.LogError"). I thought of changing the stdout and stderr streams of console by calling Console.SetOut and SetError before calling the tool's main function. For that, I would need to implement a class that inherits from TextWriter.

So my questions are:

  1. Why System.Console writes aren't automatically sent to Log of BuildSystem?
  2. Is inheriting from TextWriter and setting the streams of Console - a good solution for this problem?
  3. Perhaps someone already did this work and wrote a TextWriter implementation for sending output/error to the msbuild log?
  4. If not, where can I find some reference code that gives an example of a class that implements TextWriter?

Thanks.

0

2 Answers 2

2
Public Class TaskLogger
Inherits TextWriter

Public Enum TaskLoggerType
    out
    err
End Enum

Private m_logger As TaskLoggingHelper
Private m_logger_type As TaskLoggerType

Sub New(ByRef logger As TaskLoggingHelper, ByVal type As TaskLoggerType)
    m_logger = logger
    m_logger_type = type
End Sub

Public Overrides ReadOnly Property Encoding As System.Text.Encoding
    Get
        Return System.Text.Encoding.Default
    End Get
End Property

Public Overrides Sub WriteLine(ByVal value As String)
    Select Case m_logger_type
        Case TaskLoggerType.out
            m_logger.LogMessage(value)
        Case TaskLoggerType.err
            m_logger.LogError(value)
    End Select
End Sub
End Class

...

Public Overrides Function Execute() As Boolean
    Dim oldOut As TextWriter = Console.Out
    Dim oldErr As TextWriter = Console.Error
    Dim newOut As TextWriter = New TaskLogger(Log, TaskLogger.TaskLoggerType.out)
    Dim newErr As TextWriter = New TaskLogger(Log, TaskLogger.TaskLoggerType.err)
    Console.SetOut(newOut)
    Console.SetError(newErr)
    Dim result As Boolean = Run(...)
    Console.SetOut(oldOut)
    Console.SetOut(oldErr)
    Return result
End Function
Sign up to request clarification or add additional context in comments.

Comments

0

One option could be to have a wrapper task, inheriting from ToolTask, which just invokes this external tool, stdout/stderr messages would get logged correctly. You could even override LogEventsFromTextOutput and correctly match and log errors and warnings, which would show up in VS. Eg. LC.cs

4 Comments

When you say "invokes this external tool" do you mean by starting a new process? I could have used Exec task for that instead of wrapping the tool. My goal is to call the tool's main function many times efficiently from msbuild without starting a new process every time.
Yes, that is what I meant. New process would indeed be expensive. I would suggest changing the Console.Write* calls to Log calls, gives you better control over errors/warnings/messages. Eg, you could log debug messages from your tool with MessageImportance.Low, which wouldn't pollute regular output, but be useful when trying to debug an error. Also, changing Console's Out/Err might not play well with other things that might depend on it, being executed in parallel.
In this case, as I mentioned in the quesion, I would like to avoid changing the original tool's code. But I wonder if changing the Console's Out/Err could affect other things running in parallel... Are you sure about this? Wouldn't it affect only the same assembly from which I make the change?
AFAICS, it should affect the appdomain in which it is executing.

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.