Custom MsBuild Task - String Manipulation
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!