Click here to Skip to main content
6,597,576 members and growing! (19,711 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » .NET Framework » General     Intermediate

NAnt : Little Pretty Automatic

By Alex Kolesnichenko

Some little utility tasks for NAnt
C#, Windows, .NET 1.0, .NET 1.1VS.NET2003, Dev
Posted:17 Oct 2004
Views:86,547
Bookmarked:49 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
16 votes for this article.
Popularity: 5.37 Rating: 4.46 out of 5
1 vote, 6.3%
1

2
1 vote, 6.3%
3
3 votes, 18.8%
4
11 votes, 68.8%
5

Introduction

Do you automate your build process? I didn't, until found that one of my ASP.NET projects required too much handwork on every release: build, copy production files, update config, etc.

Ever heard of makefiles? Me too. Endless text files stuffed with ciphered spells, dashes and dots that do all magic for your build process. Forget about this — now we have NAnt.

Born in Java world and brought to .NET, NAnt let us build our programs with easy using simple human-readable XML build scripts.

Warming Up

After spending several days on learning NAnt's documentation, I got the following build script for my project:

<?xml version="1.0"?>
<project name="MyProject" default="production" basedir="..">

    <description>MyProject NANT build script</description>

    <target name="build" 
    description="Compile MyProject using Release configuration">
 <solution solutionfile="MyProject.sln" configuration="Release">
     <webmap>
  <map url="http://localhost/MyProject/Web.csproj" 
  path="Web\Web.csproj" />
  <map url="http://localhost/AchService/AchService.csproj" 
  path="AchService\AchService.csproj" />
     </webmap>
     <excludeprojects>
  <includes name="Tests\Tests.csproj"/>
     </excludeprojects>
 </solution>
    </target>

    <target name="produce" description="Copy production files">
 <!-- Copy build results to Production folder -->
 <delete dir="Build\Production" failonerror="false" />
 <copy todir="Build\Production">
     <fileset basedir="Web">
  <includes name="**.aspx" />
  <includes name="**.ascx" />
  <includes name="**.config" />
  <includes name="**.gif" />
  <includes name="**.jpg" />
  <includes name="**.mdb" />
     </fileset>
 </copy>
 <!-- Reset attributes to Normal -->
 <attrib normal="true">
     <fileset basedir="Build\Production">
  <includes name="**" />
     </fileset>
 </attrib>
 <!-- Update connection string settings -->
 <xmlpoke file="Build\Production\Web.config" 
     xpath="/configuration/MyProjectConfiguration/add
      [@key='ConnectionString']/@value"
     value="Provider=Microsoft.Jet.OLEDB.4.0;
      Data Source=D:\inetpub\wwwroot\Dev.MyProject.com\db\MyProject.mdb; 
      User ID=Admin; Password=" />
 <!-- Update path to e-mail templates -->
 <xmlpoke file="Build\Production\Web.config" 
     xpath="/configuration/MyProjectMailerConfiguration/add
     [@key='TemplatesFolder']/@value"
     value="D:\inetpub\wwwroot\Dev.MyProject.com\EmailTemplates" />
 <!-- Update path to reports templates -->
 <xmlpoke file="Build\Production\Web.config" 
     xpath="/configuration/MyProjectConfiguration/add
     [@key='ReportsTemplatesFolder']/@value"
     value="D:\inetpub\wwwroot\Dev.MyProject.com\
      landlord\Reports\Templates" />
    </target>

    <target name="production" depends="build, produce" 
     description="Build MyProject and copy production files">
 <!-- Target just refers to corresponding tasks -->
    </target>

</project>

The script builds the project, copies it to production folder and changes some key values in *.config files.

I was happy enough, but the project was growing and UI design was changing. I noticed that my script doesn't perform as expected. The problem was in the 'copy' part of the script. Take a look: to build the project, it's enough to specify solution file and map web projects to local path — the rest NAnt does itself. But when I copy cooked files, I have to specify each possible type in copy routine.

 ...
 <solution solutionfile="MyProject.sln" configuration="Release">
     <webmap>
  <map url="http://localhost/MyProject/Web.csproj" 
   path="Web\Web.csproj" />
  <map url="http://localhost/AchService/AchService.csproj"
   path="AchService\AchService.csproj" />
     </webmap>
     <excludeprojects>
  <includes name="Tests\Tests.csproj"/>
     </excludeprojects>
 </solution>
 ...
 <copy todir="Build\Production">
     <fileset basedir="Web">
  <includes name="**.aspx" />
  <includes name="**.ascx" />
  <includes name="**.config" />
  <includes name="**.gif" />
  <includes name="**.jpg" />
  <includes name="**.mdb" />
     </fileset>
 </copy>
 ...

Guess what happens when my designer adds some Flash animation to the UI?

Do It Yourself

Fortunately, NAnt was designed with extensibility in mind. And the solution is simple — develop your own task for the problem you faced.

NAnt's task is simply a descendant of NAnt.Core.Task class with overridden ExecuteTask method. The only trick is to name your assembly properly: the name should look like YourAssemblyNameTasks.dll. The assembly should be placed to %nant%\bin folder. The rest will be done by NAnt using .NET reflection magic. I developed extensions for various software in the past, but seems task development for the NAnt was the easiest.

Effortless Copy

After spending couple of days on spare time coding, I got the task that makes 'production' copy of any ASP.NET project. Now my script looks like this:

<?xml version="1.0"?>
<project name="MyProject" default="production" basedir="..">

    <description>MyProject NANT build script</description>

    <target name="build" 
    description="Compile MyProject using Release configuration">
 <solution solutionfile="MyProject.sln" configuration="Release">
     <webmap>
  <map url="http://localhost/MyProject/Web.csproj" 
  path="Web\Web.csproj" />
  <map url="http://localhost/AchService/AchService.csproj" 
  path="AchService\AchService.csproj" />
     </webmap>
     <excludeprojects>
  <includes name="Tests\Tests.csproj"/>
     </excludeprojects>
 </solution>
    </target>

    <target name="produce" description="Copy production files">
 <!-- Copy build results to Production folder -->
 <delete dir="Build\Production" failonerror="false" />
 <copywebproject project="Web\Web.csproj" 
todir="Build\Production" configuration="Release" />
 <copywebproject project="AchService\AchService.csproj" 
 todir="Build\Production\AchService" configuration="Release" />
 <!-- Reset attributes to Normal -->
 <attrib normal="true">
     <fileset basedir="Build\Production">
  <includes name="**" />
     </fileset>
 </attrib>
 <!-- Update connection string settings -->
 <xmlpoke file="Build\Production\Web.config" 
     xpath="/configuration/MyProjectConfiguration/add
     [@key='ConnectionString']/@value"
     value="Provider=Microsoft.Jet.OLEDB.4.0;
      Data Source=D:\inetpub\wwwroot\Dev.MyProject.com\db\MyProject.mdb; 
      User ID=Admin; Password=" />
 <!-- Update path to e-mail templates -->
 <xmlpoke file="Build\Production\Web.config" 
     xpath="/configuration/MyProjectMailerConfiguration/add
     [@key='TemplatesFolder']/@value"
     value="D:\inetpub\wwwroot\Dev.MyProject.com\EmailTemplates" />
 <!-- Update path to reports templates -->
 <xmlpoke file="Build\Production\Web.config" 
     xpath="/configuration/MyProjectConfiguration/add
     [@key='ReportsTemplatesFolder']/@value"
     value="D:\inetpub\wwwroot\Dev.MyProject.com\
      landlord\Reports\Templates" />
    </target>

    <target name="production" depends="build, produce" 
     description="Build MyProject and copy production files">
 <!-- Target just refers to corresponding tasks -->
    </target>

</project>

The only thing you have to care of now, is to have all production files included in the project. You can do this right-clicking on the file name in Solution Explorer and selecting 'Include in Project' command.

<copywebproject> Syntax

<copywebproject project="PATH TO PROJECT" todir="TARGET PATH" 
  configuration="CONFIGURATION OF INTEREST" />

PATH TO PROJECT is an absolute or relative path to the web project you want to copy.

TARGET PATH is an absolute or relative path to the target directory.

The task uses CONFIGURATION OF INTEREST attribute to obtain path to compiled project files.

Note that <copywebproject> task supports only web project written in C#, VB.NET or any compatible .NET language.

History

  • Version 1.0 so far.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Alex Kolesnichenko


Member

Occupation: Software Developer (Senior)
Location: United States United States

Other popular .NET Framework articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 21 of 21 (Total in Forum: 21) (Refresh)FirstPrevNext
Questionversioning in .net 2005 Pinmemberkunal_singh21:11 9 May '06  
QuestionUsing NAnt I need to Customize the Installation PinmemberChowdaryR18:53 29 Aug '05  
Generalgui to build nant files Pinmemberpaul heap17:58 24 Jun '05  
GeneralRe: gui to build nant files Pinmemberstormelf7:39 18 Sep '07  
GeneralBuilding .Net ASP Project Using NAnt PinsussAnonymous23:10 21 Jun '05  
GeneralNant send mail PinmemberSoumik Ghosh22:46 26 Apr '05  
GeneralSeparate Domain with vssget PinmemberDattaSha6:14 25 Apr '05  
GeneralNANT Incremental Build PinmemberSoumik Ghosh0:01 20 Apr '05  
GeneralRe: NANT Incremental Build PinsussAnonymous20:47 21 Apr '05  
GeneralRe: NANT Incremental Build PinsussAnonymous21:04 21 Apr '05  
GeneralConfig Override File Pinmemberdjsdjsdjsdjs4:56 29 Oct '04  
GeneralRe: Config Override File PinmemberAlex Kolesnichenko1:39 2 Nov '04  
GeneralAutomate creating building project PinmemberDipeshKhakhkhar16:28 22 Oct '04  
GeneralCopyWebProjectTask Pinmemberattackweasel5:08 18 Oct '04  
GeneralMentality PinsupporterMarc Clifton2:23 18 Oct '04  
GeneralRe: Mentality PinmemberAlex Kolesnichenko3:03 18 Oct '04  
GeneralRe: Mentality Pinmemberattackweasel4:47 18 Oct '04  
GeneralRe: Mentality PinmemberKevin McFarlane11:18 22 Oct '04  
GeneralRe: Mentality PinmemberJerryClinesmith17:35 21 Oct '04  
GeneralRe: Mentality PinmemberDGraham2:00 3 Nov '04  
GeneralRe: Mentality PinmemberTom.B.4:49 11 Jun '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 17 Oct 2004
Editor: Nishant Sivakumar
Copyright 2004 by Alex Kolesnichenko
Everything else Copyright © CodeProject, 1999-2009
Web19 | Advertise on the Code Project