Hosting MSBuild

October 29, 2007

Most people tend to use MSBuild via a few standard scenarios. Inside Visual Studio, from the command line and invoked by a continuous integration system such as Cruise Control are probably the most common.

The MSBuild framework is very flexible and we can very easily host the build engine ourselves with very little effort.

All we need to do is:

Add a reference to the MsBuild engine and framework.

image

Its often a good idea to run MSBuild in its own thread. If your application is running in an MTA thread then you’ll need to do this otherwise you will get a lot of warnings. If you want to see this try creating a Powershell script that invokes MSBuild through .net rather than calling msbuild.exe.

Create and invoke the engine:

Engine engine = new Engine();
engine.BinPath = @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\";

ConsoleLogger logger = new ConsoleLogger();

engine.RegisterLogger(logger);

bool result = engine.BuildProjectFile(
    @"C:\Projects\MyProj.csproj",
    "Build");

if (result)
{
    MessageBox.Show("Build Suceeded");
}
else
{
    MessageBox.Show("Build Failed");
}

There are two loggers that come with the base framework, the ConsoleLogger and FileLogger. Its pretty obvious from there names as to what they do. If we are hosting msbuild then chances are they won’t meet all of there needs. Fortunately we can roll our own fairly easily by implementing the ILogger interface.

public class MyLogger : ILogger

Then set up some events to handle all of the logging.

public void Initialize(IEventSource eventSource)
{
    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);

}

Write some handlers for these events. This is where we get the details of the error/warning/message and handle it as we please. It this example we are just writing it to the debug output window.

void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
{
    //Handle the logging event
    System.Diagnostics.Debug.WriteLine(e.Message);
}

Leave a Reply