Welcome!

.NET Authors: Bruce Armstrong, Marek Miesiac, Jason Dolinger, Yeshim Deniz, Liz McMillan

Related Topics: .NET

.NET: Article

Automate Application Builds Using NAnt

Managing change to ensure successful application development

After a quarter of a million lines of code had been written, the application was ready for testing. The testers, however, came back with their results alleging poor application quality. A plan had to be developed and executed quickly to address this feedback. However, the eleven-person development team was confronted with further challenges: code had to be revised due to an oversight regarding requirements and application issues, new functionalities had to be added resulting from change requests, and the finished product had to be delivered soon. The resulting code flux, nonetheless, would likely compound the quality perception problem even further.

The above scenario illustrated that, in addition to people and technology, a third element to successful application development was missing: the process of managing change. In this case, the changes consisted of the addition of new code for new functionality, the revision of existing code for the correction of identified issues, and the refactoring of code. These changes can be handled easily with the implementation of a systematic and structured build process that not only manages the expectations of the users but provides the modus operandi for the development team as well. The build process also enables the delivery of the application to the testers more often, facilitating the identification and resolution of issues early.

Several tools are available for application builds. Not only does the build tool have to be easy and quick to set up, it also has to be extensible. Additionally, it has to have a low learning curve so that the build process can be turned over to long-term resources for support and maintenance. In other words, the build tool has to be something like Apache Ant, which is widely used for Java application builds. Fortunately, there is NAnt, which is not only built on the .NET Framework but is also a lot like Ant.

The build environment can be created rapidly with NAnt as the build tool. It consists of a computer installed minimally with the following software:

  • Microsoft Windows 2000/XP Professional
  • Microsoft Visual Studio .NET 2002/2003 Professional
  • Microsoft Visual SourceSafe 6.0d
  • NAnt
The build machine should be a stand-alone computer that ensures the integrity of each build and promotes developer productivity. A dedicated computer not only creates a controlled environment in which required software for the build is installed, but it also satisfies the resource-intensive requirements of builds without unnecessarily degrading the performance of developer machines.

NAnt is a build tool that can easily be installed on a computer with the Microsoft .NET Framework. It can be obtained via download from SourceForge at http://nant.sourceforge.net/. After downloading NAnt, extract its files to the local drive of the build machine and add its path to the path system environment variable. That's it - if only all software could be installed as easily!

There are five fundamental concepts for using NAnt: build file, project, target, task, and property. The build file is constructed in XML and is named with the .build extension (see Figure 1). A build file consists of a project that contains targets. Each target, in turn, consists of tasks that execute some code. The tasks may accept parameters that reference properties defined in the build file.

The build process can be divided into five steps. First, new and revised functionalities are identified and put into a release schedule. After that, the project files are versioned (or labeled) before an application build is run. Then, the project files are retrieved by version and compiled into assemblies, which are then assembled into an application setup package. Next, the application setup files are transferred to an accessible common area and a notification about it is sent out to interested individuals. Finally, the project files are branched as soon as a version of the application is deployed into production. The frozen code resulting from the last step allows you to resolve bugs in the application that is running in production, while the regular project files are free to include new features and changes that are usually characterized as unstable.

The build file myapp.build can accomplish the last four of the above five steps of the build process with each of these steps defined as one or more targets. Following is a list of those targets (see Figure 2):

  • label: Version the project files in Visual SourceSafe using VSS's Label function.
  • getlabel: Retrieve the labeled project files in VSS via the VSS's Get function.
  • buildsetup: Build the project setup files using Visual Studio .NET.
  • copy: Copy the resulting project setup files to a path where the testers can access them.
  • branch: Create a copy of the project files in VSS.
Those targets contain tasks that reference properties defined in the build file. These properties provide information about the version, project, Visual Studio settings, and Visual SourceSafe settings. The build file can, therefore, be easily configured for other projects by just modifying the values of these properties.

These targets utilize NAnt's exec task, which executes system commands such as running Visual SourceSafe, Visual Studio .NET, and XCOPY. Although NAnt extensions for Visual SourceSafe functions are available from the NAntContrib Project, the NAnt's exec task provides complete control, removing any need to modify the NAnt extension source code.

The task within the label target uses the value of the version.number property to partially make up the value used for labeling the project in VSS. However, because the version number format of an assembly file is different from that of the setup file, the version number must be formed using a numbering scheme that works for both assembly and setup files.

The version number of an assembly file is composed of four parts of numbers (major.minor. build.revision). The product version of a setup file is comprised of the first three parts of the version number of an assembly file. The version numbering scheme should, therefore, not use the revision number. In addition, it should incorporate the build date in the minor and build numbers so as to facilitate unattended daily builds. However, for builds performed multiple times on the same day, the version number can be incremented by manually changing the version.build.suffix property value.

The significance of having the same version numbers for both assembly and setup files is to enable automatic upgrades for each new application release. To enable automatic upgrades, the following properties must be set in the setup project file:

  • DetectNewerInstalledVersion: Leave the default value to True.
  • RemovePreviousVersions: Change the default value from False to True.
  • ProductCode: Set to a new Globally Unique Identifier.
  • PackageCode: Set to a new GUID.
  • ProductVersion: Set to the first three parts of the version number.
The first two properties above can be set in Visual Studio when the setup project is first created (see Figure 3). The remaining properties are dynamically set during the build using a simple custom C# program called TweakSetup.exe, which searches for and modifies the setup project file. Another custom program, ReplaceVersion.exe, searches for the file AssemblyInfo.vb in the project working directory and subdirectories, and modifies its assembly version. The execution of these two custom programs is defined as tasks in the modifyversion target, which is executed before the buildsetup target.

The buildsetup target uses Visual Studio .NET and its corresponding solution and project files to build the assembly and setup files. The Visual Studio files conveniently package source files and build configuration information that may be changed by any member of the development team at any time. Consequently, these changes are automatically reflected in the build process, removing the need to revise the build file whenever significant modifications are made to the project.

The build file specifies a default project target named "all." This target executes all of the targets needed for regular application builds - as listed in its depends attribute - that include the label, getlabel, buildsetup, and copy tasks. The dependent targets of the all target are executed when the build file is run without any parameters.

The batch file build.bat (see Figure 4) can be used to run the build file. Executing it directly runs the build file (see Figure 5), creates the output directory if it does not exist (see Figure 6), and redirects all console output to a log file NAnt_output.txt (see Figure 7). The output file will contain the NAnt-generated message of either "BUILD SUCCEEDED" or "BUILD FAILED" at the bottom of the file to indicate if the build was successful or not. The batch file can also be executed with parameters. These parameters can be any combination of the targets found in the build file, delimited by spaces. For example, executing the batch file with the parameter branch will branch the project.

Conclusion
The build file described here performs basic build tasks. However, it can also be enhanced to do other jobs such as running NUnit unit tests using either nunit or nunit2 task, and archiving files using the zip task. Nevertheless, this build file can serve as a template that you can use to modify to build your projects.

About Eng Chong Lim

Eng Chong Lim is a Managing Consultant at Greenbrier & Russel, a business and
technology consulting firm specializing in strategic .NET projects. Recently,
Eng Chong successfully completed two large .NET projects that needed a
systematic and structured build process to ensure application quality.

Comments (2) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
malcolm9999 06/28/05 02:45:27 AM EDT

Your article is one of the few that goes beyond the basics of nant.

However you mention 2 custom programs, TweakSetup.exe, and ReplaceVersion.exe.

For your article to go beyond the, "interesting" category and into the "highly useful" category would require those two programs were either listed, or just available for download.

Thank you.

nura 05/11/05 02:17:10 AM EDT

Hi Eng,

Your article on "Automate Application Builds Using NAnt" was really usefull for us to do lots of R&D's in the install shield...in your article you have mentioned an exe called "TweakSetup" which is used to change the product code of an install shiled dynamically and have also added that it is developed using C#, can you pls let me know how to change the msi's product code dynamically using C#...of if you can send across the "TweakSetup" exe to "nura_mca@hotmail.com" it will be of great help...

Regards
nura