بنية Loggers

loggers توفر طريقة لتخصيص إخراج التصنيع الخاصة بك وعرض تحذيرات أو أخطاء أو رسائل في الاستجابة إلى الخاص أحداث البناء. كل المسجل هو كفئة.NET تطبيق ILoggerالواجهة، التي هو في تجميع Microsoft.بنية.Framework.dll.

هناك اثنين من الطرق يمكنك استخدم عند تطبيق مسجل:

  • تطبيق ILoggerالواجهة مباشرة.

  • اشتقاق الفئة من فئة المساعد، Logger، التي هو في تجميع Microsoft.بنية.Utilities.dll. LoggerيطبقILoggerو توفر تطبيقات الافتراضية لبعضILoggerالأعضاء.

سيتم شرح هذا pic إلى كيف إلى كتابة مسجلي الدخول بسيطة مشتقة من Logger، ويعرض رسائل تشغيل وحدة التحكم في استجابة إلى بنية بعض الأحداث.

التسجيل للأحداث

الغرض من المسجل هو لجمع المعلومات في بناء التقدم كما هو الذي تم الإعلام عنه من قبل مشغل البناء، ومن ثم إبلاغ تلك المعلومات بطريقة مفيدة. يجب أن تتجاوز الجميع loggers Initializeالأسلوب، الذي هو حيث regهوters المسجل للأحداث. في هذا مثال، تسجل المسجل TargetStarted، ProjectStarted، و ProjectFinishedالأحداث.

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

الاستجابة إلى أحداث

والآن بعد أن كان المسجل مسجَّل عن أحداث معينة، يحتاج إلى معالجة هذه الأحداث عند حدوثها. ل ProjectStarted، و 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);
        }

الاستجابة إلى مسجل قيم إسهاب

في بعض الحالات، قد تريد فقط يسجل المعلومات من حدث ما إذا كان ‏‫MSBuild.exe /verbosityيحتوي على تبديل بعض القيمة. 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 LoggerVerbosity Detailed.

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

Specifying a Logger

المسجل مرة واحدة هو تم تحويلها برمجياً إلى تجميع، تحتاج إلى معرفة MSBuildلاستخدام هذا المسجل أثناء الإنشاء. Th هو هو المنجز استخدام /loggerالتبديل مع ‏‫MSBuild.exe. ل المزيد من المعلومات تشغيل رموز التبديل متوفر ل ‏‫MSBuild.exe، راجع مرجع سطر الأوامر MSBuild.

comm التالية و سطر بناء مشروع 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

موارد أخرى

MSBuild Concepts