Thursday, November 08, 2007

Getting Started with NAnt - .NET Build Tool

As part of working on a installer for .NET web application, I decided to use NAnt (stands for Not Ant) which is a .NET equivalent of the popular Java based ANT build tool. If you don't know what a build tool is, check out the Build Tool article on Wikipedia. The beauty of NAnt is in the fact that you can automate many tasks and once you have a working build file, you do not have to worry about it again. Here is some of you can do with the help of NAnt:
  • Install and register ASP.NET with IIS without user intervention
  • Start/stop/pause or install windows services
  • Zip or unzip files
  • Changes values inside text or xml files
  • Create files and/or directories
  • Copy/move files and/or directories
  • Set directory and/or file security permissions
  • Much more
  • If that is not enough, you can always extend NAnt with your own custom tasks (written in VB.NET or C#)
That being said, here are the steps to get started with NAnt:
  1. Get NAnt from
  2. Get NAntContrib from
  3. Extract NAnt in "C:\Program Files\NAnt"
  4. Extract NAntContrib\bin in "C:\Program Files\NAnt\bin"
  5. Create a NAnt.bat file in C:\Windows with the following:
    @echo off
    "C:\Program Files\NAnt\bin\nant.exe" %*
  6. Create and run a sample build file. Build files can perform many functions, from compiling your .NET application to downloading files from the net. For a list of Tasks, see the NAnt Tasks list and the NAntContrib Tasks list.
Below is a sample build file that takes a currently installed web application, pre-compilies it and creates a zip file of the pre-compiled application ready to be deployed:
<?xml version="1.0"?>
<project name="Ensemble" default="deploy" basedir="." xmlns="">
 <description>Precompiles and zips the Ensemble project</description>

  <property name="debug" value="true" overwrite="true" />

 <!-- The target directory where the application will be deployed and the zip file created -->
  <property name="targetDirectory" value="." overwrite="false" />

 <!-- The temporary directory where the web application will be precompiled -->
  <property name="deployTarget" value="${path::combine(path::get-full-path(targetDirectory), 'deploy')}" overwrite="true" />

  <!-- The virtual directory that the web application resides in -->
  <property name="virtualDirectory" value="webApplication" overwrite="true" />

 <!-- The name of the zip file to create when zipping the deployed web application -->
  <property name="deployZipFilename" value="" overwrite="true" />

 <!-- The location where the zip file will be created -->
 <property name="deployZipFileLocation" value="${path::combine(path::get-full-path(targetDirectory), deployZipFilename)}" overwrite="true" />

 <!-- The location of the .NET Framework directory (for version 2) -->
  <property name="dotnetLocation" value="${framework::get-framework-directory('net-2.0')}" overwrite="true" />

  <!-- 'clean' target deletes the previously created zip file and deploy directory -->
  <target name="clean" description="Remove all generated files">
  <!-- Delete the existing zip file -->
    <delete file="${deployZipFileLocation}" if="${file::exists(deployZipFileLocation)}" />
  <!-- Delete the existing deploy directory -->
    <delete dir="${deployTarget}" if="${directory::exists(deployTarget)}" />

  <!-- 'build' target precompiles this ASP.Net application into the deployTarget directory -->
  <target name="deploy" description="Precompiles the web application and creates a zip file for it" depends="clean">
    <!-- Precompile the web application with the built-in .NET utility -->
     commandline="-nologo -fixednames -v ${virtualDirectory} "${deployTarget}""
     failonerror="true" />

    <!-- Clean up the "deployTarget" directory -->
    <!-- Delete any visual studio related files -->
    <include name="${deployTarget}/*.TempSolution" />
    <include name="${deployTarget}/**/*.scc" />
    <include name="${deployTarget}/**/*.resx" />
    <include name="${deployTarget}/**/*.txt" />
    <include name="${deployTarget}/**/*.db" />
    <include name="${deployTarget}/**/*.vssscc" />
    <!-- Delete all the files in the upload and files directory -->
    <include name="${deployTarget}/upload/**/*" />
    <include name="${deployTarget}/files/**/*" />

    <!-- Create a zip file from precompiled web application -->
    <zip zipfile="${deployZipFileLocation}" includeemptydirs="true">
      <fileset basedir="${deployTarget}">
        <include name="**/*" />

    <!-- delete the deployTarget directory -->
    <delete dir="${deployTarget}" />
// //]]>