In the last part of my MSBuild tutorial I mentioned that the target for merging config files was less than ideal. Although we were able to use the XmlRead and XmlUpdate tasks to make life easier, the list of settings to merge still needed to be maintained in the build script.
If a developer were to add a setting to, or remove a setting from, the web.config file, they would need to mirror this change in the build script. This is exactly the type of job which is easily forgotten, leading to problems further down the line.
Ideally the list of settings to merge would be self-maintaining, i.e. any settings found in the environment-specific config file would simply be enumerated and copied into web.config, rather than being explicitly listed in the build script. I decided to create my own MSBuild task for doing this. The spec for it is as follows
- Copy over the value of the debug attribute under the compilation node
- Copy over the value of the mode attribute under the customErrors node
- Enumerate each of the settings under the appSettings node and copy them over too
It has been developed to copy a setting over only if it exists in both the source and target files. As such it will not add settings missing from the target file or remove settings that are not in the source file.
It is very simple to create your own MSBuild task, just follow these steps
- Create a class which inherits from Task
- Add properties for storing the arguments the task uses. Apply the Required attribute to make the argument mandatory
- Use the LogMessage method to show progress and any errors in the command window
- Override the Execute method, returning a flag to indicate success or failure
There are plenty of examples to follow in the Community Tasks source code and a more detailed article can be found on MSDN. It is also possible to debug a task, check out the MSBuild Team Blog for an explanation.
Consuming the custom task from a build script
Having produced the task, called MergeConfig, the next step was to integrate it with the sample solution created back in part one of the tutorial. This is done by adding this statement to the build script
<UsingTask TaskName="MergeConfig" AssemblyFile="MergeConfigTask.dll" />
This piece of XML tells MSBuild that there is task called MergeConfig in the MergeConfigTask.dll. Note that the path to the dll is relative to the build script’s directory. Having done this we can add a target which will then call the new MergeConfig task, like so
<Target Name="MergeConfig"> <MergeConfig SourceConfigFilename="$(Environment).config" TargetConfigFilename="$(OutputFolder)\Web.config" /> </Target>
In addition to achieving the main goal, which was to have a self-maintaining list of settings to be merged, the use of this custom task has reduced the size of the build script, by around thirty lines. If you would like to make use of this task in your own script it can be downloaded from CodePlex. I have also updated the sample project to illustrate how the task is used.