빌드 로거

로거는 빌드 출력을 사용자 지정하고 특정 빌드 이벤트에 대한 응답에 메시지, 오류 또는 경고를 표시하는 방법을 제공합니다. 각 로거는 ITask 인터페이스를 구현하는 .NET 클래스로 구현됩니다. 이 인터페이스는 Microsoft.Build.Framework.dll 어셈블리에서 정의됩니다.

로거를 구현할 때 다음 두 가지 방법을 사용할 수 있습니다.

  • ILogger 인터페이스를 직접 구현합니다.

  • 도우미 클래스 Logger에서 클래스를 파생합니다. 이 클래스는 </xref:Microsoft.Build.Utilities.Logger> 어셈블리에서 정의됩니다. LoggerILogger를 구현하고 일부 ILogger멤버의 기본 구현을 제공합니다.

    이 항목에서는 Logger에서 파생되는 단순 로거를 작성하는 방법을 설명하고 특정 빌드 이벤트에 대한 응답으로 콘솔에 메시지를 표시합니다.

이벤트 등록

로거의 목적은 빌드 엔진에 의해 보고되는 빌드 진행률에 대한 정보를 수집한 후 해당 정보를 유용한 방식으로 보고하는 것입니다. 모든 로거는 로거가 이벤트를 등록하는 위치에 해당하는 Initialize 메서드를 재정의해야 합니다. 이 예제에서 로거는 TargetStarted, ProjectStartedProjectFinished 이벤트를 등록합니다.

public class MySimpleLogger : Logger
{
	public override void Initialize(Microsoft.Build.Framework.IEventSource eventSource)
	{
		//Register for the ProjectStarted, TargetStarted, and ProjectFinished events
		eventSource.ProjectStarted += new ProjectStartedEventHandler(eventSource_ProjectStarted);
		eventSource.TargetStarted += new TargetStartedEventHandler(eventSource_TargetStarted);
		eventSource.ProjectFinished += new ProjectFinishedEventHandler(eventSource_ProjectFinished);
	}

이벤트에 응답

로거를 특정 이벤트에 등록했으므로 이제 이벤트가 발생할 때 해당 이벤트를 처리해야 합니다. For the ProjectStartedProjectFinished 이벤트의 경우 로거는 이벤트와 관련된 프로젝트 파일의 짧은 구 및 이름을 씁니다. 로거에서 발생한 모든 메시지는 콘솔 창에 기록됩니다.


void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
{
	Console.WriteLine("Project Started: " + e.ProjectFile);			
}

void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
{
	Console.WriteLine("Project Finished: " + e.ProjectFile);
}

로거 자세한 정도 값에 대한 응답

일부 경우에 MSBuild.exe /verbosity 스위치에 특정 값이 포함되어 있을 때만 이벤트의 정보를 로깅하려고 할 수 있습니다. 이 예제에서 TargetStarted 이벤트 처리기는 /verbosity 스위치에 의해 설정된 Verbosity 속성이 LoggerVerbosityDetailed인 경우에만 메시지를 로깅합니다.

void eventSource_TargetStarted(object sender, TargetStartedEventArgs e)
{
	if (Verbosity == LoggerVerbosity.Detailed)
	{
		Console.WriteLine("Target Started: " + e.TargetName);
	}
}

로거 지정

로거가 어셈블리로 컴파일되면 빌드하는 동안 MSBuild에 해당 로거를 사용하도록 지시해야 합니다. 이 작업은 MSBuild.exe와 함께 /logger 스위치를 사용하여 수행합니다. MSBuild.exe에 대해 사용할 수 있는 스위치에 대한 자세한 내용은 명령줄 참조를 참조하세요.

다음 명령줄은 프로젝트 MyProject.csproj를 빌드하고 SimpleLogger.dll에서 구현된 로거 클래스를 사용합니다. /nologo 스위치는 배너 및 저작권 메시지를 숨기고 /noconsolelogger 스위치는 기본 MSBuild 콘솔 로거를 사용하지 않도록 설정합니다.

MSBuild /nologo /noconsolelogger /logger:SimpleLogger.dll  

다음 명령줄은 동일한 로거를 사용하지만 Verbosity 수준 Detailed를 사용하여 프로젝트를 빌드합니다.

MSBuild /nologo /noconsolelogger /logger:SimpleLogger.dll /verbosity:Detailed  

예제

설명

다음 예제에서는 로거에 대한 전체 코드를 보여 줍니다.

코드

using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;

namespace SimpleLogger
{

	public class MySimpleLogger : Logger
	{
		public override void Initialize(Microsoft.Build.Framework.IEventSource eventSource)
		{
			//Register for the ProjectStarted, TargetStarted, and ProjectFinished events
			eventSource.ProjectStarted += new ProjectStartedEventHandler(eventSource_ProjectStarted);
			eventSource.TargetStarted += new TargetStartedEventHandler(eventSource_TargetStarted);
			eventSource.ProjectFinished += new ProjectFinishedEventHandler(eventSource_ProjectFinished);
		}

		void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
		{
			Console.WriteLine("Project Started: " + e.ProjectFile);			
		}

		void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
		{
			Console.WriteLine("Project Finished: " + e.ProjectFile);
		}
		void eventSource_TargetStarted(object sender, TargetStartedEventArgs e)
		{
			if (Verbosity == LoggerVerbosity.Detailed)
			{
				Console.WriteLine("Target Started: " + e.TargetName);
			}
		}
	}
}

설명

예제

설명

다음 예제에서는 로그를 콘솔 창에 표시하지 않고 파일에 쓰는 로거를 구현하는 방법을 보여 줍니다.

코드

using System;
using System.IO;
using System.Security;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MyLoggers
{
	// This logger will derive from the Microsoft.Build.Utilities.Logger class,
	// which provides it with getters and setters for Verbosity and Parameters,
	// and a default empty Shutdown() implementation.
	public class BasicFileLogger : Logger
	{
		/// <summary>
		/// Initialize is guaranteed to be called by MSBuild at the start of the build
		/// before any events are raised.
		/// </summary>
		public override void Initialize(IEventSource eventSource)
		{
			// The name of the log file should be passed as the first item in the
			// "parameters" specification in the /logger switch.  It is required
			// to pass a log file to this logger. Other loggers may have zero or more than 
			// one parameters.
			if (null == Parameters)
			{
				throw new LoggerException("Log file was not set.");
			}
			string[] parameters = Parameters.Split(';');
			
			string logFile = parameters[0];
			if (String.IsNullOrEmpty(logFile))
			{
				throw new LoggerException("Log file was not set.");
			}
			
			if (parameters.Length > 1)
			{
				throw new LoggerException("Too many parameters passed.");
			}
			
			try
			{
				// Open the file
				this.streamWriter = new StreamWriter(logFile);
			}
			catch (Exception ex)
			{
				if
				(
					ex is UnauthorizedAccessException
					|| ex is ArgumentNullException
					|| ex is PathTooLongException
					|| ex is DirectoryNotFoundException
					|| ex is NotSupportedException
					|| ex is ArgumentException
					|| ex is SecurityException
					|| ex is IOException
				)
				{
					throw new LoggerException("Failed to create log file: " + ex.Message);
				}
				else
				{
					// Unexpected failure
					throw;
				}
			}

			// For brevity, we'll only register for certain event types. Loggers can also
			// register to handle TargetStarted/Finished and other events.
			eventSource.ProjectStarted += new ProjectStartedEventHandler(eventSource_ProjectStarted);
			eventSource.TaskStarted += new TaskStartedEventHandler(eventSource_TaskStarted);
			eventSource.MessageRaised += new BuildMessageEventHandler(eventSource_MessageRaised);
			eventSource.WarningRaised += new BuildWarningEventHandler(eventSource_WarningRaised);
			eventSource.ErrorRaised += new BuildErrorEventHandler(eventSource_ErrorRaised);
			eventSource.ProjectFinished += new ProjectFinishedEventHandler(eventSource_ProjectFinished);
		}

		void eventSource_ErrorRaised(object sender, BuildErrorEventArgs e)
		{
			// BuildErrorEventArgs adds LineNumber, ColumnNumber, File, amongst other parameters
			string line = String.Format(": ERROR {0}({1},{2}): ", e.File, e.LineNumber, e.ColumnNumber);
			WriteLineWithSenderAndMessage(line, e);
		}
		
		void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
		{
			// BuildWarningEventArgs adds LineNumber, ColumnNumber, File, amongst other parameters
			string line = String.Format(": Warning {0}({1},{2}): ", e.File, e.LineNumber, e.ColumnNumber);
			WriteLineWithSenderAndMessage(line, e);
		}

		void eventSource_MessageRaised(object sender, BuildMessageEventArgs e)
		{
			// BuildMessageEventArgs adds Importance to BuildEventArgs
			// Let's take account of the verbosity setting we've been passed in deciding whether to log the message
			if ((e.Importance == MessageImportance.High && IsVerbosityAtLeast(LoggerVerbosity.Minimal))
				|| (e.Importance == MessageImportance.Normal && IsVerbosityAtLeast(LoggerVerbosity.Normal))
				|| (e.Importance == MessageImportance.Low && IsVerbosityAtLeast(LoggerVerbosity.Detailed))				
				)
			{
				WriteLineWithSenderAndMessage(String.Empty, e);
			}
		}

		void eventSource_TaskStarted(object sender, TaskStartedEventArgs e)
		{
			// TaskStartedEventArgs adds ProjectFile, TaskFile, TaskName
			// To keep this log clean, this logger will ignore these events.
		}
		
		void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
		{
			// ProjectStartedEventArgs adds ProjectFile, TargetNames
			// Just the regular message string is good enough here, so just display that.
			WriteLine(String.Empty, e);
			indent++;
		}

		void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
		{
			// The regular message string is good enough here too.
			indent--;
			WriteLine(String.Empty, e);
		}
		
		/// <summary>
		/// Write a line to the log, adding the SenderName and Message
		/// (these parameters are on all MSBuild event argument objects)
		/// </summary>
		private void WriteLineWithSenderAndMessage(string line, BuildEventArgs e)
		{
			if (0 == String.Compare(e.SenderName, "MSBuild", true /*ignore case*/))
			{
				// Well, if the sender name is MSBuild, let's leave it out for prettiness
				WriteLine(line, e);
			}
			else
			{
				WriteLine(e.SenderName + ": " + line, e);
			}
		}
		
		/// <summary>
		/// Just write a line to the log
		/// </summary>
		private void WriteLine(string line, BuildEventArgs e)
		{
			for (int i = indent; i > 0; i--)
			{
				streamWriter.Write("\t");
			}
			streamWriter.WriteLine(line + e.Message);
		}
		
		/// <summary>
		/// Shutdown() is guaranteed to be called by MSBuild at the end of the build, after all 
		/// events have been raised.
		/// </summary>
		public override void Shutdown()
		{
			// Done logging, let go of the file
			streamWriter.Close();
		}

		private StreamWriter streamWriter;
		private int indent;
	}
}

설명

참고 항목

빌드 로그 가져오기
MSBuild 개념