ビルド ロガーBuild Loggers

ロガーを使うと、ビルドの出力をカスタマイズして、特定のビルド イベントに対する応答のメッセージ、エラー、または警告を表示できます。Loggers provide a way for you to customize the output of your build and display messages, errors, or warnings in response to specific build events. 各ロガーは、Microsoft.Build.Framework.dll アセンブリで定義されている ILogger インターフェイスを実装する .NET クラスとして実装されます。Each logger is implemented as a .NET class that implements the ILogger interface, which is defined in the Microsoft.Build.Framework.dll assembly.

ロガーを実装するには 2 つの方法があります。There are two approaches you can use when implementing a logger:

  • ILogger インターフェイスを直接実装します。Implement the ILogger interface directly.

  • Microsoft.Build.Utilities.dll アセンブリで定義されているヘルパー クラス Logger からクラスを継承します。Derive your class from the helper class, Logger, which is defined in the Microsoft.Build.Utilities.dll assembly. LoggerILogger を実装し、一部の ILogger メンバーの既定の実装を提供します。Logger implements ILogger and provides default implementations of some ILogger members.

    このトピックでは、Logger を継承し、特定のビルド イベントに対する応答のメッセージをコンソールに表示する簡単なロガーを作成する方法を説明します。This topic will explain how to write a simple logger that derives from Logger, and displays messages on the console in response to certain build events.

イベントの登録Registering for Events

ロガーの目的は、ビルド エンジンによって報告されたビルドの進行状況に関する情報を収集し、役に立つ方法でその情報を報告することです。The purpose of a logger is to gather information on build progress as it is reported by the build engine, and then report that information in a useful way. すべてのロガーは、イベントを登録する Initialize メソッドを無視する必要があります。All loggers must override the Initialize method, which is where the logger registers for events. この例では、ロガーは TargetStartedProjectStartedProjectFinished イベントを登録しています。In this example, the logger registers for the TargetStarted, ProjectStarted, and ProjectFinished events.

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);
	}

イベントへの応答Responding to Events

特定のイベントを登録したロガーは、発生したイベントを処理する必要があります。Now that the logger is registered for specific events, it needs to handle those events when they occur. ProjectStartedProjectFinished イベントの場合、ロガーは短い語句と、イベントに関連するプロジェクト ファイルの名前を書き込むだけです。For the ProjectStarted, and ProjectFinished events, the logger simply writes a short phrase and the name of the project file involved in the event. ロガーからのすべてのメッセージは、コンソール ウィンドウに書き込まれます。All messages from the logger are written to the console window.


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);
}

ロガーの詳細値への応答Responding to Logger Verbosity Values

MSBuild.exe の /verbosity スイッチに特定の値が含まれる場合にのみ、イベントから情報を記録したいことがあります。In some cases, you may want to only log information from an event if the MSBuild.exe /verbosity switch contains a certain value. 次の例の TargetStarted イベント ハンドラーは、/verbosity スイッチによって設定される Verbosity プロパティが LoggerVerbosityDetailed に等しい場合にのみ、メッセージを記録します。In this example, the TargetStarted event handler only logs a message if the Verbosity property, which is set by the /verbosity switch, is equal to LoggerVerbosityDetailed.

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

ロガーの指定Specifying a Logger

ロガーがアセンブリにコンパイルされた後は、ビルドの間にそのロガーを使うように MSBuildMSBuild に指定する必要があります。Once the logger is compiled into an assembly, you need to tell MSBuildMSBuild to use that logger during builds. これは、MSBuild.exe で /logger スイッチを使って行います。This is done using the /logger switch with MSBuild.exe. MSBuild.exe で使用可能なスイッチについて詳しくは、「コマンド ライン リファレンス」をご覧ください。For more information on the switches available for MSBuild.exe, see Command-Line Reference.

次のコマンド ラインは、プロジェクト MyProject.csproj をビルドし、SimpleLogger.dll で実装されているロガー クラスを使います。The following command line builds the project MyProject.csproj and uses the logger class implemented in SimpleLogger.dll. /nologo スイッチはバナーと著作権のメッセージを非表示にし、/noconsolelogger スイッチは既定の MSBuildMSBuild コンソール ロガーを無効にします。The /nologo switch hides the banner and copyright message and the /noconsolelogger switch disables the default MSBuildMSBuild console logger.

MSBuild /nologo /noconsolelogger /logger:SimpleLogger.dll  

次のコマンド ラインは同じロガーでプロジェクトをビルドしますが、Verbosity レベルは Detailed です。The following command line builds the project with the same logger, but with a Verbosity level of Detailed.

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

Example

説明Description

次の例には、ロガーの完全なコードが含まれます。The following example contains the complete code for the logger.

コードCode

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);
			}
		}
	}
}

コメントComments

Example

説明Description

次の例では、コンソール ウィンドウに表示するのではなくファイルにログを書き込むロガーを実装する方法を示します。The following example shows how to implement a logger that writes the log to a file rather than displaying it in the console window.

コードCode

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;
	}
}

コメントComments

関連項目See Also

ビルド ログの取得 Obtaining Build Logs
MSBuild の概念MSBuild Concepts