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" #>
Property value: StartDir= $(StartDir)
Item Group value: TextFiles = @(TextFiles)
- execute it through a call to ExecuteT4Template in your build target:
<ExecuteT4Template TemplatePath="T4Sample.tt" OutputPath="c:\T4SampleOutput.txt"/>
- and it produces the following output:
Property value: StartDir= C:
Item Group value: TextFiles = \zeros.txt
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:
- 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;
- 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: ExecuteT4Template.cs (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.