Create a MSBuild Task

MSBuild comes with a lot of excellent built-in build tasks and there are also well-supported open source Build tasks such as MSBuild Community Tasks. I have found myself wanting something not available in any of those tasks. In this post I’ll walk through how I built a build task which meets my needs.

The Problem

I have a build script, which gets the latest code, compiles the code and runs functional tests. The build script is run on many different machines. The functional tests depend on  entries existing in the local hosts file; if those entries do not exist, ALL the functional tests will fail. Rather than running (and failing) all the functional tests, I want the build to fail before the tests start.

Build a MSBuild task

1. Create a project

2. Add references

3. Implement Microsoft.Build.Utilities.Task

Here’s the code to test if a list of hostnames are all valid.


public class CheckHostNameBuildTask : Task
{
    ///
<summary> /// Comma-separated list of hostnames to check.
 /// </summary>
    [Required]
    public ITaskItem HostNamesToCheck { get; set; }

    public override bool Execute()
    {
        var missingHostNames = new List();

        foreach (string hostname in GetHostNames())
        {
            try
            {
                Dns.GetHostAddresses(hostname);
            }
            catch (Exception)
            {
                missingHostNames.Add(hostname);
            }
        }

        if (missingHostNames.Count > 0)
        {
            string errorMsg = string.Format("Failed to find host name: [{0}]",
                                            string.Join(",", missingHostNames));

            BuildEngine.LogErrorEvent(new BuildErrorEventArgs(
                    "CheckHostNameBuildTask", string.Empty, "CheckHostNameBuildTask.dll",
                    0, 0, 0, 0, errorMsg, string.Empty, string.Empty));

            return false;
        }
        return true;
    }

    private IEnumerable GetHostNames()
    {
        return HostNamesToCheck.ItemSpec.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
    }
}

4. Reference the Build task in a project

  <UsingTask AssemblyFile=".\BuildTask.dll" TaskName="BuildTask.CheckHostNameBuildTask" />
  <Target Name="BeforeBuild">
    <CheckHostNameBuildTask HostNamesToCheck="domanwhichdoesnotexist.com"/>
  </Target>

Final Thoughts

That’s about it. It’s pretty easy to add a custom build task. Building the build task and referencing it in another project is a little frustrating. Visual Studio tends to acquire a lock on the DLL. I found I had to close Visual Studio and re-open it to update the DLL.

Code can be found here:
https://github.com/marksl/msbuild-task

Advertisements
This entry was posted in C# and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s