问题
There is a command line argument '/logger' for msbuild that allows you to specify a custom implemented logger when building. (https://msdn.microsoft.com/en-us/library/ms171471.aspx)
msbuild.exe /?
...
/logger: Use this logger to log events from MSBuild. To specify multiple loggers, specify each logger separately. The syntax is: [,][;] The syntax is: [.] The syntax is: {[,] | } The are optional, and are passed to the logger exactly as you typed them. (Short form: /l) Examples: /logger:XMLLogger,MyLogger,Version=1.0.2,Culture=neutral /logger:XMLLogger,C:\Loggers\MyLogger.dll;OutputAsHTML
I'd like to implement my own custom logger. To make sure the rest of my development team run with it whenever they build; I want apply some sort of setting directly within the project file itself.
Ideally this would mean if someone built the project through the IDE, msbuild command line and/or using the devenv commandline the custom logger would always be run.
What setting, property or other mechanism could be used within the project file to set a custom logger?
回答1:
The answer is no. Loggers are configuration settings for build engine. You cannot start the build, and then configure the build engine. Here is a snippet of code from MSDN -- it shows normal flow of the build engine initialization:
// 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();
There might be ways to hack it, because every MSBuild task receives a reference to the build engine object (IBuildEngine interface), that you could typecast to Microsoft.BuildEngine.Engine and call RegisterLogger method. However be aware that this would be just wrong, because you will be modifying engine globally for all projects in the build, and it might not work or stop working any time.
回答2:
As S.T. says: there is no real proper way to do this. However with a rather simple hack, namely overriding the Build
target, you can achieve what you want. Not sure if i would recommend it though, overriding targets like that might break builds.
Anyway. I don't like storing assemblies in version control so let's start with source for the custom logger, put this in a file CustomLogger.cs. The custom logger will be built on the fly - however if you want of course you may skip this and use the assembly directly:
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 );
}
}
}
Then in the project file add this after the line importing 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>
When building within VS or on the commandline when no target is specified, the default target Build
will be called. This normally builds but here we override it and make it do more interesting stuff: it will first build your custom logger dll via BuildCustomLoggerDll
then invoke msbuild manually through the Exec
task and specify to use the customlogger of choice. The target built is ActualBuild
and this is a copy of the original Build
target found in C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Common.CurrentVersion.targets
- so this example if for VS2013 and C# projects and probably needs modifications for other versions and other languages. But it works, and logs through the custom logger.
来源:https://stackoverflow.com/questions/28733875/can-a-msbuild-custom-logger-be-specified-within-a-project-file