An MSBuild task to execute T4 templates

[Source: https://geekswithblogs.net/EltonStoneman]

I was looking for an MSBuild task which could execute a T4 template, replacing tags in the template with the value of properties or item groups from the build - giving your T4 templates access to all the runtime values used in the build scripts. So you start with a T4 template like this:

<#@ template language="C#" #>

<#@ output extension=".txt" #>

<#@ assembly name="System.dll" #>

***START

Property value: StartDir= $(StartDir)

Item Group value: TextFiles = @(TextFiles)

***END

- execute it through a call to ExecuteT4Template in your build target:

<PropertyGroup>

<StartDir>C:</StartDir>

</PropertyGroup>

<ItemGroup>

<TextFiles Include="$(BuildOutputDir)\*.txt"/>

</ItemGroup>

<Target Name="ExecuteTemplate">

<ExecuteT4Template TemplatePath="T4Sample.tt" OutputPath="c:\T4SampleOutput.txt"/>

</Target>

- and it produces the following output:

***START

Property value: StartDir= C:

Item Group value: TextFiles = \zeros.txt

***END

There wasn't one that I could find so I put a simple one together. A couple of fiddly things worth noting if you do something similar:

  1. the project's property values are not exposed to the executing task in an accessible way, so you have to reflect around BuildEngine to get hold of the executing project;
  2. if you don't want to write an ITextTemplatingEngineHost or rely on a GAX or other host, you'll end up shelling out to TextTransform.exe (as I have).

Full source for the task is here: (note this uses version 1.1 of the TextTransform tool).

A couple of things to note: this task will update all instances of property and item tags in the template - $(propertyName) or @(itemGroupName) (it's not clever enough to deal with %(itemGroupName.ValueName))- with the value from MSBuild, if the named property/item group exists in the project. Potentially you may want to leave certain tags in place in the template, in which case you'll need to ensure there are no matching properties in the build, or extend the task to take a list of names to ignore.

Also, if you're using a value in your script which is the output from another task, then the task which produces the output must be in a separate target which completes before the call to ExecuteT4Template. MSBuild seems only to store properties/item groups from task outputs when targets are completed, so if the output is created in the same target as the T4 task, the property won't be registered and the tag in the template won't be replaced.

I have a couple of other tasks which all relate to deploying BizTalk and ESB Service Providers, so I'll add them to the ESBSimpleSamples CodePlex project along with this one.

This article is part of the GWB Archives. Original Author: Elton Stoneman

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.