【问题标题】: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# 项目,可能需要针对其他版本和其他语言进行修改。但它可以工作,并通过自定义记录器进行记录。