NAnt is great. I have a script that compiles all my source files, builds the standalone installation packages, fires off Virtual PC for testing, and it can even FTP the installation package to my client's site. It seems like there's nothing NAnt can't do. But I needed to peel off the version number from the executable, and I couldn't find any easy way to do this in NAnt. Fortunately, I discovered that it's really not that hard to create a custom task in NAnt in C#, then use it from the target.
Basically, you have to create a <script> block (as shown below) and create a class that inherits from Task. The TaskName attribute is what you will use in the main NAnt script to call it. Any property with a TaskAttribute attribute can be used as an XML attribute in the script, and you can set Required=true to require it. The Task object has the Project property, which can be used to access anything at all to do with the build process. I use it here to set a NAnt property and log to StdOut. NAnt will compile the C# code on the fly (if you did everything correctly) and voila, anything you can think of is now possible.
Here is a sample from the build script I created.
<project name="SomeNAntProject" default="DefaultTarget">
<property name="version.number" value="0.0.0.0" />
<target name="DefaultTarget">
<getversioninfo filename="C:\Folder\MyExecutable.exe" />
<echo message="${version.number}" />
</target>
<script language="C#">
<code>
<![CDATA[
[TaskName("getversioninfo")]
public class GetVersionInfoTask: Task {
private string _fileName;
[TaskAttribute("filename", Required=true)]
public string FileName {
get {return _fileName; }
set {_fileName = value; }
}
protected override void ExecuteTask() {
System.Diagnostics.FileVersionInfo fvi =
System.Diagnostics.FileVersionInfo.GetVersionInfo(_fileName);
Project.Properties["version.number"] = fvi.ProductVersion;
Project.Log(Level.Info,
" [script] Got version info for " + _fileName);
}
}
]]>
</code>
</script>
</project>