【问题标题】:Can a MSBuild custom Logger be specified within a Project file?可以在项目文件中指定 MSBuild 自定义记录器吗?
【发布时间】:2015-02-26 03:20:10
【问题描述】:

msbuild 有一个命令行参数“/logger”,允许您在构建时指定自定义实现的记录器。 (https://msdn.microsoft.com/en-us/library/ms171471.aspx)

msbuild.exe /?

...

/logger:使用此记录器记录来自 MSBuild 的事件。指定 多个记录器,分别指定每个记录器。 语法是: [,][;] 语法是: [.] 语法是: {[,] | } 是可选的,并且通过 完全按照您输入的方式发送到记录器。 (缩写:/l) 例子: /logger:XMLLogger,MyLogger,Version=1.0.2,Culture=neutral /logger:XMLLogger,C:\Loggers\MyLogger.dll;OutputAsHTML

我想实现我自己的自定义记录器。确保我的开发团队的其他成员在构建时使用它;我想直接在项目文件中应用某种设置。

理想情况下,这意味着如果有人通过 IDE、msbuild 命令行和/或使用 devenv 命令行构建项目,自定义记录器将始终运行。

可以在项目文件中使用哪些设置、属性或其他机制来设置自定义记录器?

【问题讨论】:

    标签: logging build msbuild build-process


    【解决方案1】:

    答案是否定的。记录器是构建引擎的配置设置。您无法启动构建,然后配置构建引擎。这是来自MSDN 的一段代码——它显示了构建引擎初始化的正常流程:

    // Instantiate a new Engine object
    Engine engine = new Engine();
    
    ...
    
    // Instantiate a new FileLogger to generate build log
    FileLogger logger = new FileLogger();
    // Register the logger with the engine
    engine.RegisterLogger(logger);
    
    // Build a project file
    bool success = engine.BuildProjectFile(@"c:\temp\validate.proj");
    
    //Unregister all loggers to close the log file
    engine.UnregisterAllLoggers();
    

    可能有破解它的方法,因为每个 MSBuild 任务都会收到对构建引擎对象(IBuildEngine 接口)的引用,您可以将其类型转换为 Microsoft.BuildEngine.Engine 并调用 RegisterLogger 方法。但是请注意,这是错误的,因为您将为构建中的所有项目全局修改引擎,并且它可能无法正常工作或随时停止工作。

    【讨论】:

      【解决方案2】:

      作为 S.T.说:没有真正正确的方法可以做到这一点。然而,通过一个相当简单的 hack,即覆盖 Build 目标,您可以实现您想要的。不确定我是否会推荐它,覆盖这样的目标可能会破坏构建。

      无论如何。我不喜欢将程序集存储在版本控制中,所以让我们从自定义记录器的源代码开始,将其放在文件 CustomLogger.cs 中。自定义记录器将即时构建 - 但是,如果您当然愿意,您可以跳过此步骤并直接使用程序集:

      using Microsoft.Build.Framework;
      using Microsoft.Build.Utilities;
      
      namespace CustomLogger
      {
        public class ScanLogger : Logger
        {
          public override void Initialize( IEventSource eventSource )
          {
            eventSource.MessageRaised += ( s, e ) =>
              System.Console.WriteLine( "HI THERE - " + e.Message );
          }
        }
      }
      

      然后在项目文件中添加这个行导入Microsoft.CSharp.targets:

      <PropertyGroup>
        <LoggerDll>Customlogger.dll</LoggerDll>
      </PropertyGroup>
      
      <Target Name="BuildCustomLoggerDll">
        <Csc Sources="$(MSBuildThisFileDirectory)customlogger.cs"
             References="System.dll;mscorlib.dll;Microsoft.Build.Framework.dll;Microsoft.Build.Utilities.v4.0.dll"
             TargetType="Library" OutputAssembly="$(MSBuildThisFileDirectory)$(LoggerDll)"/>
      </Target>
      
      <Target Name="ActualBuild"
              Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
              DependsOnTargets="$(BuildDependsOn)"
              Returns="$(TargetPath)"/>
      
      <Target Name="Build">
        <Exec Command="C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe $(MSBuildThisFile) /t:ActualBuild /noconsolelogger /l:$(MSBuildThisFileDirectory)$(LoggerDll)"/>
      </Target>
      

      在没有指定目标的情况下在 VS 或命令行上构建时,将调用默认目标 Build。这通常会构建,但在这里我们会覆盖它并让它做更多有趣的事情:它将首先通过 BuildCustomLoggerDll 构建您的自定义记录器 dll,然后通过 Exec 任务手动调用 msbuild 并指定使用选择的自定义记录器。构建的目标是ActualBuild,这是在C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Common.CurrentVersion.targets 中找到的原始Build 目标的副本——所以这个例子适用于VS2013 和C# 项目,可能需要针对其他版本和其他语言进行修改。但它可以工作,并通过自定义记录器进行记录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多