1. Skip to navigation
  2. Skip to content

Entries tagged “msbuild”

Custom MsBuild Task - String Manipulation

written by Michael Trier, on Jul 27, 2007 12:27:00 AM.

I stated in a previous blog post that I’ve been working with MsBuild lately to automate the build process for a client of mine. One of the things that amazed me is the thin list of available built-in Tasks that come with MsBuild. The good news is there are several open source projects out there that are making custom MsBuild tasks available. There’s a lot of great things out there and I definitely recommend the following open source packages:

  • Sdc – A package put together by a group out of Microsoft Australia.
  • MsBuild Community Tasks – Put together by the folks at Tigris (creators of Subversion).

There is some overlap between the packages, so you’ll just have to pick and choose what works best for you. I’ve had some problems with each of these packages, but it’s not surprising since they both continue to be improved upon.

One of the things I found missing from the standard MsBuild tasks is the ability to do any kind of string manipulation. With the scripts that I was putting together I found that I didn’t want to have multiple Properties for various forms of the same string. For instance:



    ToDo
    https://michaeltrier.com/svn/todo/trunk
    http://localhost/TODOTEST/

To fix this problem we would like to be able to replace every instance of ToDo and it’s case variations to just a single Property name. For example:



    ToDo
    https://michaeltrier.com/svn/$(ProjectName)/trunk
    http://localhost/$(ProjectName)TEST/

Unfortunately I was not able to find any Tasks in the MsBuild system that allow for that sort of string manipulation. The good news is that creating custom MsBuild tasks is very easy. To get started we only need to create a class that implements the Microsoft.Build.Framework.ITask interface and properly implements the Execute method. A very simple custom task might look like this:


using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;

namespace Eminent.MsBuild.Tasks
{
    public class Math : Task
    {
        System.Int32 _x;
        System.Int32 _y;

        [Required]
        public System.Int32 X
        {
            get {return _x; } 
            set { _x = x;    }
        }

        [Required]
        public System.Int32 Y
        {
            get { return _y; } 
            set { _y = y; }
        }

        [Output]
        public string Result
        {
            get { return _x + _y; }
        }

        public override bool Execute()
        {
            return true;
        }
    }
}

The above code is pretty simple, but quite honestly it doesn’t get too much more complicated than that for most tasks. In this case we’re using the Required attribute to specify the properties that are required for the Task. In this case both the X and Y properties are required. We’re also using the Output attribute to indicate properties that have Output variables available from within our Task. The final piece of logic is the implementation of the Execute method. In this case all of the functionality is handled by the Result property so all we need to do in that case is return true to show that the task executed successfully.

The Execute method could do all sorts of things, like connect to a Subversion repository to export source code, or to launch some task in the background. The possibilities are really limitless.

If we were to call the above task it would look something like the following:




    
        
    
    

The UsingTask element allows us to import our newly created assembly and let MsBuild know that we want to make available the specified task name. Once the task is available we just need to call the task with the required properties and then collect up the results in the Output element.

So, back to the task at hand. I mentioned that MsBuild didn’t seem to have built-in tasks for string manipulation so I proceeded to create a custom task assembly that implements my string manipulation tasks. At first I thought I would have a bunch of separate tasks, such as LowerCase, UpperCase, PascalCase, Pluralize etc… Then it occurred to me I can combine these all under one task that has multiple Output elements. This allows the user to pull out the item that they want. Once fully implemented I can have a task that allows me to do something like the following:



    

You can download the complete task here. Enjoy!

Fun With MsBuild

written by Michael Trier, on Jul 24, 2007 8:28:00 PM.

Lately I’ve been automating a client’s build process using MsBuild. Their original scripts were written using NAnt, and just consisted of the fundamentals of compile, docs, code analysis, etc… This is a .Net project as I’m sure you’ve guessed. Although I’ve played around with MsBuild in the past, this is the first time I’ve completely automated a build system and integrated it into a Continuous Integration process. It’s been a fun project, but there are some real gotchas when working with MsBuild, and the availability of good documentation out there is pretty slim. This means a lot of trial and error, with lots of tasks thrown in for good measure.

One thing that got me early on is the fact that ItemGroup gets evaluated at the time the file is read not when the property is referenced. For instance, let’s say we have a Target that looks something like the following:



    



    

This Target simply copies files from a source location to a release location. This works fine if at the time the script is run (at the start, when the script is first evaluated) files exist in the directory structure specified. But lets say instead that our Target looked something like:



    



    
    
    
    

The above code will not work, because at the the time the script is evaluated the OutputFiles do not exist since they are created by the MsBuild task. This seems like a bug to me, but apparently this is by design. Often people not realizing this problem will experience a situation where it works intermittently because in some cases they may be re-running the task and the files are still there from a prior run.

To get around this problem we use the CreateItem task. CreateItem allows us to Create an ItemGroup on the fly as part of our Target process. For instance, using the CreateItem task we can rewrite the above so that it actually works consistently.



    
    
    
    
    
        
    
    

Problem solved! Working with MsBuild is a lot of fun; it is a very flexible environment, but as you can tell there are some things to be watchful about.