CruiseControl.Net Tutorial – Part 2

15 06 2008

1. Introduction (part 1)
2. Resources (part 1)
3. Installation (part 1)
3.1. Install CruiseControl.NET (part 1)
3.2. Create a CCNet Website in IIS (part 1)
3.3. Install Nunit (part 1)
4. CruiseControl.NET Server Configuration – General (part 1)
5. Structure of a ‘Project’ Configuration File (part 1)
6. Source Control Block (part 1)
7. Trigger Block (part 1)
8. Labeller Block (part 1)
9. Tasks Block
10. MsBuild Task
10.1. MSBuild and ReferencePath – CruiseControl.NET not resolving reference to Nunit
10.2. An Alternative MSBuild Logger – Christian Rodemeyer’s MsBuildToCCNet
10.3. CruiseControl.NET Webdashboard fails in finding images if not installed in virtual directory
10.4. MSBuildToCCNET reports wrong number of compiled projects
10.5. CruiseControl.NET, MsBuild Task and Resources – Assembly Linker
10.6. CruiseControl.NET, MsBuild Task and Web Application projects
11. Nunit Task
11.1. Nunit Task
11.2. Executable Task
12. Publishers Block
13. PreBuild Block
13.1. Install Nant
13.2. Nant Fundamentals

This article is the second one of a series dedicated to CruiseControl.Net.
In the first part (which you can find here) we installed it and had an overview of how to configure it.
Then we started to configure a project file: we instructed the Source Control Block to use Subversion, the Trigger Block to check it periodically and the Labeller Block to use: svnRevisionLabeller
In this second article we will see the Tasks Block and I will point out some issues that might arise and provide solutions as well.

Thanks to Frank Geerlings for making me aware of a casing problem with the xml samples.
By talking with WordPress support it came out that there was a little bug and they suggested me
how to fix the problem.

9. Tasks Block

The tasks block represents how the build of the project actually takes place.
In our example we will use an MsBuild Task to accomplish the main purpose of our project, which is to compile the versioned Visual Studio solution.
After that we will use an Executable Task to run our unit tests, if the build succeeds.
Let’s see the whole Tasks Block, at first:

<!-- compiles working copy -- >
<projectFile>DummySolution.sln</projectFile >
    <buildArgs>/noconsolelogger /v:quiet
      /p:ReferencePath="C:\Program Files\NUnit 2.4.7\bin"
    <targets>ReBuild</targets >
    <timeout>600</timeout >
    <logger>c:\Program Files\CruiseControl.NET\server\
      Rodemeyer.MsBuildToCCNet.dll</logger >
<!-- launches nunit tests on working copy -- >
    <executable>C:\Program Files\NUnit 2.4.7\
    </executable >
      /nologo Dummy.sln.nunit

Let's focus on the <strong>MsBuild Task</strong> first and see how we can configure and customize it:

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettuttasksblock"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>
<h3><a title="ccnettutmsbuildtask" name="ccnettutmsbuildtask"></a><span style="font-size:small;color:#993300;">10. MsBuild Task</span></h3>
Let's have a look at the meaning of the xml nodes children of the <strong>&lt;msbuild&gt;</strong> node:

<strong>&lt;executable&gt;</strong>: contains the path to the msbuild executable file. You don't really need to set it because the default value is the standard installation path: <span style="color:#808080;">C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</span>.
I decided to set it explicitly just to be sure about it .
<strong>&lt;workingDirectory&gt;</strong>: is the directory in which MsBuild will be run, so it must be the directory containing our project's checked out working copy. You can provide a path relative to the current project's workinDirectory but I preferred to provide the full path. Actually, the path to the CCNET checked out working copy is the same as the <strong>&lt;workingDirectory&gt;</strong> field of the <strong>Source Control Block</strong>.
<strong>&lt;projectFile&gt;</strong>: is the name of the project to build. MsBuild accepts a Visual Studio solution file as the project file to build. Obviously the <strong>MsBuild Task</strong> accepts it as well.
<strong>&lt;buildArgs&gt;</strong> This row provides additional command line arguments to MsBuild. We tell it not to log events to the console (<span style="color:#808080;">/noconsolelogger</span>), to build the Debug configuration (<span style="color:#808080;">/p:Configuration=Debug</span>) and to provide a reduced output (<span style="color:#808080;">/v:quiet</span>).
As far as the <span style="color:#808080;">/p:ReferencePath</span> buildArg is concerned it is worth to talk extensively about a problem that could arise with Nunit, so have a look at <a href="#ccnettutreferencepath" target="_self">paragraph 10.1</a>.
<h4><a title="ccnettutreferencepath" name="ccnettutreferencepath"></a><span style="font-size:x-small;color:#993300;">10.1 MSBuild and ReferencePath - CruiseControl.NET not resolving reference to Nunit</span></h4>
It could happen that CCNET is not able to locate Nunit (or some other dependency assembly) depending on how your project file has been created by Visual Studio.
Open your project file (<strong>DummyProject.csproj</strong>) with a text editor (e.g.: Notepad++). If you find an entry as follows in it:

&#91;sourcecode language='xml'&#93;
  <Reference Include="nunit.framework, Version=,
    Culture=neutral, PublicKeyToken=96d09a1eb7f44a77,
    processorArchitecture=MSIL" />

with no &lt;HintPath&gt; associated to the Nunit &lt;Reference&gt; it could be that CCNET will not be able to resolve that reference if you don't register nunit.framework.dll in the server's GAC.

You can make sure that CCNET is able to resolve the dependency by providing an alternative search path in which to look for.
Each assembly referenced in the Visual Studio project file needs to be located by MSBUild at compile time.
The location of the referenced assemblies is resolved by MSBuild by looking in several locations in a particular search order (as explained <a title="reference path vs2005" href="" target="_blank">here</a>).
We could modify the .csproj file by providing a  value as a child node of the  node, e.g.:

&#91;sourcecode language='xml'&#93;
<Reference Include="DummyLibrary, Version=,
    Culture=neutral, processorArchitecture=MSIL">

This approach has two drawbacks:
	<li> the hintpath is a relative path, thus making the build success depend on the location of the project relative to the referenced assembly (this could be a problem if we reference an external assembly);</li>
	<li>we need to modify each Visual Studio project file by hand  and we don't want to do it!</li>
Fortunately there's an easy way out:
We can override all the project specific settings for path resolving by passing a <strong>ReferencePath </strong>property from the MSBuild command line.
Such property accepts as value a list of paths (<em>MSBuild DummySolution.sln  /p:"ReferencePath=&lt;Path1;Path2;Path3&gt;"</em>) and it is checked by the build process before checking other locations (<strong>HintPath</strong> for example).
So the way to provide an alternative search path from the command line is to pass as argument a <strong>ReferencePath</strong> property.
This is the reason why the command line provided in the &lt;buildArgs&gt; field contains the <strong>ReferencePath</strong> property pointing to the Nunit install path:
<span style="color:#808080;">/p:ReferencePath="C:\Program Files\NUnit 2.4.7\bin"</span>.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutmsbuildtask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>

<span style="font-size:x-small;color:#993300;">end of paragraph 10.1</span>
<span style="font-size:x-small;color:#993300;">continues paragraph 10. MsBuild Task</span>

Let's go on with the analysis of the xml nodes children of the &lt;msbuild&gt; node:
<strong>&lt;targets&gt;</strong> specifies which targets to build in this msbuild project file. It represents the MSbuild's /target command line argument. We set it to <strong>Rebuild</strong> (clean and build).
<strong>&lt;timeout&gt;</strong> is the number of seconds before assuming that the process has hung. If timeout is exceeded the process will be killed.
<strong>&lt;logger&gt;</strong> specifies the path to the assembly containing the logger to use to format the log output of MSbuild .
If you don't want to use the alternative logger that I used in the configuration shown above, you can rely on the default logger as explained here and skip the following
<a href="#ccnettutrodemeyer" target="_self">paragraph 10.2</a>.
To use the default logger:
	<li>leave out the &lt;logger&gt; field,</li>
	<li>download the assembly containing the default xml logger <a title="default logger" href="" target="_blank">here</a> (find info <a title="loggers description" href="" target="_blank">here</a>),</li>
	<li>copy the downloaded assembly (<strong>ThoughtWorks.CruiseControl.MSBuild.dll</strong>) to the folder: <span style="color:#808080;">C:\%ProgramFiles%\CruiseControl.NET\server</span>.</li>
I suggest to use the alternative logger (by Christian Rodemeyer) as explained in the following paragraph. The RodeMeyer's logger provide lighter msbuild output and his modified stylesheets provide much more readable display of such information.
<h4><a title="ccnettutrodemeyer" name="ccnettutrodemeyer"></a><span style="font-size:x-small;color:#993300;">10.2. An Alternative MSBuild Logger - Christian Rodemeyer's MsBuildToCCNet</span></h4>
I chose to use a logger alternative to the default one: Christian Rodemeyer's MsBuildToCCNet.
You can find it at:  <a title="rodemeyer page" href="" target="_blank">Improved MSBuild Integration</a>.  From there either you can download separately the assembly and all related stuff needed to correctly display the results from Rodemeyer's logger or you can download a zip file with the whole project and source code.

In the page cited above you can find detailed instructions on how the logger works and how it should be configured.
In the current paragraph I'll illustrate the installation process and add some useful tips for making it work.
I suggest to download the full project that comes in a zip file named: (download <a title="download rodemeyer" href="" target="_blank">here</a>).
Unzipping the package you will have a directory named: MsBuildToCCNet. Inside this directory you will find, among the rest, a directory named <strong>Release</strong>, containing the assembly: <strong>Rodemeyer.MsBuildToCCnet.dll</strong>.
Just copy the assembly to the <span style="color:#808080;">\CruiseControl.NET\server</span> folder (e.g.: <span style="color:#808080;">c:\Program Files\CruiseControl.NET\server\</span>).
There's another subdirectory of the <span style="color:#808080;">MsBuildToCCNet</span> folder, named <span style="color:#808080;">ccnet</span> where you can find the resources needed to correctly display the logs produced by Rodemeyer's logger. Those resources are:
<strong>cruisecontrol.css</strong> and

You need to use those two files and to configure the Webdshboard:
	<li>Move into your CruiseControl.NET Webdashboard folder, under the path: <span style="color:#808080;">C:\%ProgramFiles%\CruiseControl.NET\webdashboard</span> (e.g.: <span style="color:#808080;">c:\Program Files\CruiseControl.NET\webdashboard\</span>) and back up the file: <strong>cruisecontrol.css</strong>.
Then replace it with the <strong>cruisecontrol.css</strong> file you found in the Rodemeyer's MsBuildToCCNet folder (e.g.: copy <span style="color:#808080;">MsBuildToCCNet\ccnet\cruisecontrol.css</span> to <span style="color:#808080;">c:\Program Files\CruiseControl.NET\webdashboard\cruisecontrol.css</span>);</li>
	<li>There's a subdirectory of the CruiseControl.NET Webdashboard folder, named: <strong>xsl</strong>.
You need to copy the other resource (<strong>msbuild2ccnet.xsl</strong>) you found in the <span style="color:#808080;">MsBuildToCCNet\ccnet</span> folder in that directory: <span style="color:#808080;">C:\%ProgramFiles%\CruiseControl.NET\webdashboard\xsl\</span>;</li>
	<li>You need to modify the <strong>dashboard.config</strong> file in the CruiseControl.NET Webdashboard folder in order to correctly show the output of the logger.
Being that we're talking about the Webdashboard configuration I will show you all the changes you will need to do to let it work with the following three components (even if we'll see two of them only in the following paragraphs):
	<li> MsBuildToCCNet</li>
	<li> Nunit integration</li>
	<li> FxCop integration</li>
First of all choose a 32 x 32 jpg image representing a smiling icon and place it in the CruiseControl.NET Webdashboard folder: <span style="color:#808080;">C:\%ProgramFiles%\CruiseControl.NET\webdashboard</span>.
Rename the image file: <em>your_happy_image.jpg</em> and, when a new build succeeds, you'll obtain a smiling icon in the Webdashboard report! (you can find a sample image <a title="happy image" href="" target="_blank">here</a>).
Then open <span style="color:#808080;">CruiseControl.NET\webdashboard\xsl\msbuild2ccnet.xsl</span> and go to line 24:

&#91;sourcecode language='xml'&#93;
<xsl :if test="@error_count = 0 and @warning_count = 0">
<td><img src="/ccnet/your_happy_image.jpg"
           alt="Happy Image :-)" /> Juchuu !!!</td>

replace the <em>img src</em> attribute: <span style="color:#808080;">/ccnet/your_happy_image.jpg</span> with <span style="color:#808080;">/your_happy_image.jpg</span> if you configured iis with a new website for the webdashboard instead of a virtual directory. If you're usign the default virtual directory named <strong>ccnet</strong>, don't modify that row.
Next you need to locate the field: <strong>&lt;buildPlugins&gt;</strong> in <span style="color:#808080;">C:\%ProgramFiles%\CruiseControl.NET\webdashboard\dashboard.config</span> and arrange or delete its children nodes in order to obtain the following configuration (remember to back up the file first):

&#91;sourcecode language='xml'&#93;
  <buildlogbuildplugin />
  <xslreportbuildplugin description="NUnit Details"
       xslFileName="xsl\tests.xsl" />
  <xslreportbuildplugin description="NUnit Timings"
       xslFileName="xsl\timing.xsl" />
   <xslreportbuildplugin description="FxCop Report"
       xslFileName="xsl\FxCopReport.xsl" />

As you can see, such configuration includes also stylesheet files for nunit and fxcop integration. We will soon configure the server to integrate those components.</li>
<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutmsbuildtask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>

<span style="font-size:x-small;color:#993300;">end of paragraph 10.2</span>
<span style="font-size:x-small;color:#993300;">continues paragraph 10. MsBuild Task</span>

While adding the smiling image in the previous paragraph we had to change the path in the xsl file.
The same problem could arise with other stylesheet files if you configured the webdashboard to be a website instead that a virtual directory named ccnet.
Have a look at the next paragraph for details:
<h4><a title="ccnettutwebdashboardimages" name="ccnettutwebdashboardimages"></a><span style="font-size:x-small;color:#993300;">10.3. CruiseControl.NET Webdashboard Fails in Finding Images if Not Installed in Virtual Directory</span></h4>
If you unchecked <span style="color:#808080;">'Create virtual directory in IIS for Web dashboard'</span> as shown in part 1 of this tutorial at <a title="install part 1" href="" target="_blank">3.1. Install CruiseControl.NET</a> and installed the Webdashboard as a new website as shown in the paragraph: <a title="create iis website part 1" href="" target="_blank">3.2. Create a CCNet Website in IIS</a>, the webdashboard could have problems in resolving image paths.
You will realize it as soon as you will configure the server to integrate nunit or fxcop (will see it in  following paragraphs).
To make sure not to have this problems you must modify the following files:
under: <span style="color:#808080;">C:\%ProgramFiles%\CruiseControl.NET\webdashboard\</span>

you have to replace all the paths relative to the root of the website with relative paths, e.g:

in the file: <strong>xsl\tests.xsl</strong> you should replace all entries like:

&#91;sourcecode language='xml'&#93;
eImg.src = "<xsl :value-of select="$applicationPath"/>/images/arrow_minus_small.gif";


&#91;sourcecode language='xml'&#93;
eImg.src = "<xsl :value-of select="$applicationPath"/>images/arrow_minus_small.gif";

and entries like:

&#91;sourcecode language='xml'&#93;
<img src="{$applicationPath}/images/fxcop-error.gif"/>


&#91;sourcecode language='xml'&#93;
<img src="{$applicationPath}images/fxcop-error.gif"/>

that is, you simply need to delete the leading 'forward slash' at the beginning of the path (just before the 'images' folder name).

you need to accomplish the same task with the file <strong>xsl\fxcop-summary.xsl</strong>, e.g.:

you should replace entries like:

&#91;sourcecode language='xml'&#93;
<xsl :attribute name="src"><xsl :value-of select="$applicationPath" />/images/fxcop-critical-error.gif</xsl>


&#91;sourcecode language='xml'&#93;
<xsl :attribute name="src"><xsl :value-of select="$applicationPath" />images/fxcop-critical-error.gif</xsl>

Actually, you should find all paths to images in those two files and delete the leading forward slash.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutmsbuildtask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>

<span style="font-size:x-small;color:#993300;">end of paragraph 10.3</span>
<span style="font-size:x-small;color:#993300;">continues paragraph 10. MsBuild Task</span>

Back to the MSBuildToCCNET alternative Logger for MsBuild, I will explain now why I decided to recompile the source code instead of using the assembly provided: <span style="color:#808080;">MsBuildToCCNet\Release\Rodemeyer.MsBuildToCCnet.dll</span>
<h4><a title="ccnettutnumberofprojects" name="ccnettutnumberofprojects"></a><span style="font-size:x-small;color:#993300;">10.4. MSBuildToCCNET Reports Wrong Number of Compiled Projects</span></h4>
I found that MsBuildToCCNet reported the wrong number of projects in the webdashboard in the page reporting the details of the last build.
There's a row that sounds like the following, displaied in that page:

<span style="color:#0000ff;">'15 Projects built with 2 warnings'</span>

Looking at the source code (in the file: <strong>Logger.cs</strong>) I realized that the list of <em>Project</em> type instances includes the solution file (<span style="color:#666699;">DummySolution.sln</span>) and a <em>Project</em> object named "<span style="color:#ff6600;">MSBuild</span>", somehow representing the MsBuild process.
Appearently this is the reason why the reported number of projects is wrong.
I still haven't tried to contact the author so I don't know very well how the Logger is supposed to work as far as this count is concerned.
As a workaround I modified the following row:

&#91;sourcecode language='csharp'&#93;

turning it into:

&#91;sourcecode language='csharp'&#93;
                     XmlConvert.ToString(projects.Count - 2));

in the 'WriteLog(XmlWriter w)' method (file: <strong>Logger.cs</strong> at row 104).

This seems having fixed the problem with no side effects.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutmsbuildtask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>

<span style="font-size:x-small;color:#993300;">end of paragraph 10.4</span>
<span style="font-size:x-small;color:#993300;">continues paragraph 10. MsBuild Task</span>

You could have problems running msbuild task if your server machine (the one in which you installed CruiseControl.NET) is not updated with all the software installed in a developer workstation. Let's see which problems could arise:
<h4><a title="ccnettutassemblylinker" name="ccnettutassemblylinker"></a><span style="font-size:x-small;color:#993300;">10.5. CruiseControl.NET, MsBuild Task and Resources - Assembly Linker</span></h4>
If you want to provide localization for any of your projects or somehow use resources files (.resx) you will get an error during the build on the CruiseControl.NET server if MsBuild is not able to locate the Assembly Linker.
The error should look something like:

<span style="color:#ff0000;">C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets(1950,9): error MSB3011: "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\AL.exe" was not found. Either 1) Install the .NET Framework SDK, which will install AL.exe. Or 2) Pass the correct location of AL.exe into the "ToolPath" parameter of the AL task.</span>

AL.exe is used to produce the satellite assemblies and the executable file is placed in the .NET framework directory.
But Al.exe is a .Net Framework SDK tool. It is not included in .Net Framework 2.0 runtime installation.
You need to install the .NET framework SDK on the server machine if you don't want to encounter this problem.
If you want to solve this particular issue in a tricky way without installing the whole SDK, you can copy <strong>al.exe.config</strong> e <strong>al.exe</strong> from a developer workstation and place them in the <span style="color:#808080;">C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727</span> directory on the server machine.
This is how I solved the problem but I suggest you to install the .NET framework SDK on the server machine.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutmsbuildtask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>
<h4><a title="ccnettutwebappprojects" name="ccnettutwebappprojects"></a><span style="font-size:x-small;color:#993300;">10.6. CruiseControl.NET, MsBuild Task and Web Application projects</span></h4>
A particular note is due for Web projects.
Updating Visual Studio 2005 you get the SP1. Together with the Service Pack 1 for Visual Studio you get the WebApplication project template.
Such template lets us add a new kind of project to our solution: a web site project structured exactly like any other Visual Studio project.
So you can quit creating new websites (<strong>File --&gt; New --&gt; Web Site...</strong>) and start creating new WebApplication projects (<strong>File --&gt; New --&gt; Project...</strong> and then choose '<strong>ASP.NET Web Application</strong>').

In order to use WebApplication projects you need to have Visual Studio installed on your machine and the WebApplication project plugin (that comes with the Visual Studio 2005 SP1).
If the server in which CruiseControl.NET server is running is not a develpment workstation you will get an error when trying to build a WebApplication project, beacuse you miss those two prerequisites.

You can easily fix this problem: you simply need to copy the file: <strong>Microsoft.WebApplication.targets</strong> that you can find under:
<span style="color:#808080;">"C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\WebApplications\"</span>
from a development workstation and paste it to the corresponding path on the server machine (creating the directories in the path if needed).

Additionally, if you're using an ASP.NET AJAX Enabled WebApplication as the web project template you need to install the aspnet-ajax extensions as well.
You can find the installer (ASPAJAXExtSetup.msi) for .NET framework 2.0 <a title=" ajax download" href=";displaylang=en" target="_blank">here</a>

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutmsbuildtask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>
<h3><a title="ccnettutnunittask" name="ccnettutnunittask"></a><span style="font-size:small;color:#993300;">11. Nunit Task</span></h3>
The second Task Block that you find in the xml fragment <a title="xml msbuild task" href="#ccnettutsamplexml" target="_self">above</a> is an Executable Task used to instruct CruiseControl.NET to run unit tests with Nunit.

At first I tried to use a <strong>Nunit Task Block</strong> but I soon realized that it was not good for me because it was not possible to provide arguments to the task that should be used as arguments of the Nunit command-line executable.

This is a problem because there's no way to let the Nunit task be aware of Nunit categories.
For those who don't know, Nunit lets you specify a '<em>Category</em>' attribute in test methods, with the following syntax:

&#91;sourcecode language='csharp'&#93;
public void VeryLongTest()
{ /* ... */ }

This attribute allows you to instruct Nunit to treat all the methods belonging to the same category in the same way.
Usually what we want to do is to exclude a cluster of tests from running.
Typically we exclude tests that take too much to run, using the following syntax with the nunit command-line tool:

<strong>nunit-console.exe /exclude:LongRunning,AnotherCategoryName</strong>

You can configure excluded categories in nunit GUI as well, by clicking the '<strong>Categories</strong>' tab in the top left corner.
A list of available categories will be shown. Just select the categories of interest and click the <strong>Add</strong> button.
Then check the <strong>Exclude these categories</strong> checkbox at the bottom of the page and run the nunit project.

It is very useful to be able to exclude some categories of tests from the continuous integration environment, still being able to run them on developer machines.

This is the reason why I recently submitted a patch to CruiseControl.Net adding support for Nunit categories.
It's not included in the official release yet, because I submitted it too late for this purpose.
However you can find it in the current build which is publicly available at: <a href="">ccnetlive</a>. The patch is included starting from build: <a href="">3591</a>.
So now you have two chances to use categories:
	<li>If you really want to use the last officially released version, read the <a href="#ccnettutnunittask2">paragraph 11.2</a> about how to use an Executable Task (the method described can be useful also if you want to use any other unsupported Nunit command line argument);</li>
	<li><span style="text-decoration:underline;">Instead if you can download the latest build from ccnetlive you will be able to specify categories</span> inside the Nunit Task block, as explained in <a href="#ccnettutnunittask">paragraph 11.1</a></li>
<h4><a title="ccnettutnunittask1" name="ccnettutnunittask1"></a><span style="font-size:x-small;color:#993300;">11.1. Nunit Task</span></h4>
If you downloaded the most recent build and followed the installation instructions (see: <a href="">3. Installation</a>) you can go on reading this paragraph.
If you installed the official release or a build older than, you can still modify your installation with the following instructions:

download the zipped package (<a href="">here</a>) or source code. Unzip it in a temporary directory and locate the assembly: ThoughtWorks.CruiseControl.Core.dll (which, for the zip package, is in the directory: 'server').
Copy and replace it to the original one in your CCNET installation directory (back up the original one first) that should be: <span style="color:#808080;">Program Files\CruiseControl.NET\server</span>.

That's it! Now you can use the CruiseControl.NET's Nunit Task Block also for specifying Nunit categories (see: <a href=";r=2.4.8">Nunit categories</a> for reference).

It is possible to specify a list of the categories of tests that we want to be excluded.
It is possible, as well, to specify a list of the only categories that we want to be included as allowed by the Nunit Command-line or GUI interface.
The configuration syntax for the Nunit task becomes:

&#91;sourcecode language='xml'&#93;
<path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
	<excludedCategory>Category 2</excludedCategory>

for excluded categories, or:

&#91;sourcecode language='xml'&#93;
<path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
	<includedCategory>Category 2</includedCategory>

for included categories. You can find the official reference at <a href="" target="_blank">this page</a> on the official website.

The Nunit task output log file is automatically integrated in the CCNET build results.
So you don't need to specify the Merge task (needed if you use the procedure explaine in paragraph 11.2 instead of this one) in the Publishers block as explained in <a href="#ccnettutpublishersblock">paragraph 12</a>:

&#91;sourcecode language='xml'&#93;

Instead you still need to delete the previous Nunit log file before each build process as explained in the <a href="#ccnettutprebuildblock">paragraph 13 - PreBuild Block</a>.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutnunittask"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>
<h4><a title="ccnettutnunittask2" name="ccnettutnunittask2"></a><span style="font-size:x-small;color:#993300;">11.2. Executable Task</span></h4>
If you're working with the official release of CruiseControl.Net (release 1.4) Nunit Task Block syntax only allows you to specify the target solution and little more. In our example it would be:

&#91;sourcecode language='xml'&#93;
<path>C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe

where <strong>Dummy.sln.nunit</strong> is the Nunit project file for our solution.

The solution I strongly suggest is to replace the Nunit Task with an Executable Task like the one shown below:

&#91;sourcecode language='xml'&#93;
    C:\Program Files\NUnit 2.4.7\bin\nunit-console.exe
    /nologo Dummy.sln.nunit

You only need to specify the full path to the Nunit command-line executable file in the <strong>&lt;executable&gt;</strong> field and the command-line arguments in the <strong>&lt;buildArgs&gt;</strong> field.

In the <strong>&lt;buildArgs&gt;</strong> field you specify arguments as if provided directly to <strong>nunit-console.exe</strong>:
	<li>specify the path to the file in which nunit will write its output: <span style="color:#808080;">/xml:..\project1CCnetArtifacts\nunit-results.xml</span>.
The file should be produced in the artifactDirectory of the current CCNET project.
By default the executable run by an executable task is run in the Project Working Directory, so the path to the output file is relative to such directory.</li>
	<li> You can pass many things as Nunit targets (assemblies, Visual Studio projects or Nunit project files). I suggest to create an Nunit project and pass it as argument to <strong>nunit-console.exe</strong> as shown in the sample above (where the nunit project file is called: <strong>Dummy.sln.nunit</strong>).</li>
	<li> you can then add: <span style="color:#808080;">/exclude:LongRunning,AnotherCategoryName</span> thus excluding unwanted tests.</li>
Specifying the name of the output file is not enough.
In order to make the output written by nunit in the file nunit-results.xml (arbitrary name specified in the buildArgs tag), available to CruiseControl.NET we need to use a File Merge Task.
If we used Nunit task the output file would have been automatically merged with other output for CruiseControl.NET.
Using the Executable Task we need to explicitly configure CruiseControl.NET to merge the Nunit output file in the log file parsed by CruiseControl.NET.
We will tell CruiseControl.NET to do it at the end of the build process, namely in the Publishers section.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutnunittask2"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>
<h3><a title="ccnettutpublishersblock" name="ccnettutpublishersblock"></a><span style="font-size:small;color:#993300;">12. Publishers Block</span></h3>
We will add a <strong>File Merge Task</strong> at the beginning of the Publishers section. You can see below the publishers section as it is defined in our project configuration file:

&#91;sourcecode language='xml'&#93;
  <xmllogger />
  <statistics />
  <modificationHistory onlyLogWhenChangesFound="true" />
  <artifactcleanup cleanUpMethod="KeepLastXBuilds"
    cleanUpValue="20" />

The File Merge Task specifies the paths to the files that we want to be merged by the <strong>Xml Log Publisher Task</strong> with the rest of its own output (you don't need to specify nunit output file if you used the Nunit Task as in paragraph <a href="#ccnettutnunittask1">11.1. Nunit Task</a>).
All of this output is placed by default in the <strong>buildlogs</strong> directory under the Project's Artifact Directory.
So the <strong>File Merge Task</strong> should appear before the <strong>Xml Log Publisher Task</strong> in the publishers section.
The <strong>Xml Log Publisher Task</strong> ('<strong>xmllogger</strong>') is needed for making the web dashboard work correctly.
The '<strong>statistics</strong>' field collects and updates statistics for each build. You can see them clicking: <strong>View Statistics</strong> on the left side of the Web Dashboard.
The '<strong>modificationHistory</strong>' field logs all the modifications for each build. With <strong>onlyLogWhenChangesFound</strong> you can choose to log info only for builds happened when changes take place (not for forced builds). You can see the modification history by clicking: <strong>View Modification History</strong> on the left side of the Web Dashboard.

I then added an '<strong>artifactcleanup</strong>' field in order to keep memory of the last 20 builds only.
This task allows us to choose between two clean up modes of the past build logs:
- deleting logs older than a specified number of days
- keeping only a specified number of logs: the more recent ones (cleanUpMethod="KeepLastXBuilds")

In the sample above we typed the second choice specifying 20 as cleanUpValue thus telling CruiseControl.NET to keep the log files for the last 20 builds only.

<a href="#ccnettut2top"><span style="font-size:80%;color:red;">→ top of post</span></a>
<a href="#ccnettutpublishersblock"><span style="font-size:80%;color:red;">→ top of paragraph</span></a>
<h3><a title="ccnettutprebuildblock" name="ccnettutprebuildblock"></a><span style="font-size:small;color:#993300;">13. PreBuild Block</span></h3>
There's another issue to solve when integrating Nunit using either an <strong>Exec Task</strong> or the <strong>Nunit Task</strong>: the Nunit log file is not deleted after the build succeeds or fails.
So upon the next build we'll still have the old Nunit log file until the Task running Nunit is executed.
To understand what I'm going to explain now, keep in mind that if a task in the <strong>Tasks Block</strong> fails all the subsequent tasks in the block will be skipped while the tasks in the <strong>Publishers Block</strong> will be executed.

If, during the next build, the <strong>MSBuild Task</strong> fails, the <strong>Exec Task (Nunit Task)</strong> launching Nunit isn't executed at all so the <strong>File Merge Task</strong> will merge the previous Nunit log file with the current <strong>Xml Log Publisher</strong> output, thus leading to an incorrect report: still displaying the Nunit results relative to the previous build.
We would obtain the <span style="text-decoration:underline;">current</span> MSBuild report but the <span style="text-decoration:underline;">old</span> Nunit report.
This behavior can lead to misunderstanding of the results so it is a good practice to delete the old Nunit log file before every new build takes place.

The place to accomplish this task is the <strong>PreBuild Block</strong>.
I used a <strong>Nant</strong> build file to drive the steps needed to obtain the desired result (simply delete a file if it exists).
<h4><a title="ccnettutinstallnant" name="ccnettutinstallnant"></a><span style="font-size:x-small;color:#993300;">13.1. Install Nant</span></h4>
You need to install the <a title="nant homepage" href="" target="_blank">Nant</a> Build tool on the server machine.
Just download the zip package: from <a title="nant download" href=";big_mirror=0" target="_blank">here</a> and unzip it into the folder: <span style="color:#808080;">C:\Program Files\Nant</span>.
<h4><a title="ccnettutnantfundamentals" name="ccnettutnantfundamentals"></a><span style="font-size:x-small;color:#993300;">13.2. Nant Fundamentals</span></h4>
<strong>Nant</strong> is a build tool driven by xml configuration files (Nant build files).
When you call nant.exe from the command line and you don't specify a build file (you can specify one passing as argument: <span style="color:#ff6600;">-buildfile:pathToDir\</span>) NAnt looks for a file ending with .build (e.g.: in the current directory. If it finds such file, it uses it as the reference for the tasks to execute.

The file structure is shown in the following sample xml file:

&#91;sourcecode language='xml'&#93;
< ?xml version="1.0"?>
<project name="dummy" default="target1" basedir=".">
	<description>dummy project</description>
	<target name="target1" description="target1 description">
	    ... (a list of Nant tasks will be placed here)
	<target name="target2" description="target2 description">
		<delete file="pathToFile\FileName"
                failonerror="false" />
		... (a list of other Nant tasks will be placed here)

A build file contains one <strong>&lt;project&gt;</strong> field with one or more children <strong>&lt;target&gt;</strong> fields each containing different Nant tasks (e.g.: the <strong>&lt;delete&gt;</strong> task).
When invoking <strong>nant.exe</strong> you can specify the name of the target to be executed and Nant will execute all the tasks contained in that target. If you don't provide a target, the default one will be executed (i.e. the one specified in the '<span style="color:#ff6600;">default</span>' attribute of the <strong>&lt;project&gt;</strong> field).

<span style="font-size:x-small;color:#993300;">end of paragraph 13.2</span>
<span style="font-size:x-small;color:#993300;">continues paragraph 13. PreBuild Block</span>

Once you've got Nant installed on the server machine you have to create a file named and place it, for convenience, in the directory in which you placed all the CruiseControl.NET related stuff (in this example: <span style="color:#808080;">C:\develop\CCnet</span>).

At the moment we need just one target to delete Nunit log files. Later we will add another target.
The actual file content is the following:

&#91;sourcecode language='xml'&#93;
< ?xml version="1.0"?>
<project name="Dummy" default="cleanNunit" basedir=".">
  <description>CCNET Tasks</description>
  <target name="cleanNunit"
         description="removes nunit log file">
    <delete file="${CCNetArtifactDirectory}\nunit-results.xml"
          failonerror="false" />

When we tell Nant to execute the '<span style="color:#ff6600;">cleanNunit</span>' target, the delete task will be executed and the <strong>nunit-results.xml</strong> file will be deleted.
We use one of the environment variables provided by CCNET to retrieve the path to the artifact directory: <span style="color:#ff6600;">${CCNetArtifactDirectory}</span> so this Nant build file will only work when run from CruiseControl.NET.

In the <strong>Prebuild Block</strong> we will instruct CruiseControl.NET to run a Nant task by adding a CruiseControl.NET <strong>Nant Task Block</strong>.
Such block lets us instruct CruiseControl.NET to execute Nant and lets us specify a Nant build file and the list of Nant targets to execute.
Remember that we named the build file: <strong></strong> and we placed it in the directory: <span style="color:#808080;">C:\develop\CCnet</span>.
Now we provide this information to the CruiseControl.NET <strong>Nant Task Block</strong> as shown in the following example:

&#91;sourcecode language='xml'&#93;
<!-- clean nunit output to avoid CCNET reporting
       about previous build tests if current build fails -->
    <executable>C:\Program Filse\Nant\bin\nant.exe

the <executable> field specifies the path to the version of nant.exe you want to run,
the <baseDirectory> specifies the directory to run the NAnt process in,
<nologo> passes the -nologo argument to the Nant command line,
<buildFile> specifies the path to the build file to use (relative to the <baseDirectory>),
<targetList> is used to specify a list of targets, each one in a <target> field.

Now we can be sure that each build has the Nunit log file deleted before being executed.

→ top of post
→ top of paragraph

<< CruiseControl.Net Tutorial – Part 1

As soon as possible I will post the third and last part of this tutorial

kick it on




41 responses

16 06 2008
Reflective Perspective - Chris Alcock » The Morning Brew #115

[…] CruiseControl.Net Tutorial – Part 2 – Matteo continues his series on Cruise Control Setup and configuration with part two, covering the actual build and publish. […]

17 06 2008

Tutorial is excellent. One stop information required to setup CruiseControl.Net I just followed the tutorial and i don’t have to look elsewhere because of any issues occurred in between. All the blocks are nicely explained.
Tones of thanks for this.

18 06 2008

You’re welcome,
I’m very happy that you find it useful.
I will add some more details when I will add part 3.
Stay tuned!

25 06 2008

Good aritcle!

25 06 2008

Good aritcle!
I have a problem
I don’t now what testing tool use with the CruiseControl
for web applications with Ajax (C#) .Net
can you suggest me one?

pd:sorry my bad ingles

25 06 2008

Hello Lorena,

If I guessed your question right, you’re looking for a tool to test ajax enabled web pages.
I heard about a tool serving this purpose. I still didn’t try it but it seems to be good.
It allows you to write web tests from inside Nunit and supports both Internet Explorer and FireFox.
It could be the tool for you.
The name is Watin and you can find it here:


11 07 2008


This is an excellent article. I was completely new to CruiseControl and was having trouble gathering all the relevant information to get me up to speed. I then stumbled upon your blog and all became clear. Can’t wait to see Part 3

Many thanks indeed.

14 07 2008

Hello Colin,

thank you very much for appreciating my article!
I’m sorry for the delay in publishing part 3, I’m having hard time at work in these days.
I will try to be quicker in the next days and I hope you will like it when published.


21 07 2008

Hi I am facing a issues with the cruise control results. CC is showing up a build as failed when it is a success. Is there any fix for this? How can I sort this issue?

Thanks for your post it was simply superb.

22 07 2008

Hello Kishore,

you should tell me something more about the problem you’re facing.
I will be glad to help you if I can.
It could be useful if you post an example of your configuration or the relevant point of your log file.
I sent you an email about it.

Thank you for the compliments

12 08 2008

Thanks very much for the article. Very useful.

17 09 2008

brilliant stuff. thank you! looking forward to part 3.

17 09 2008

I’m very sorry for the delay, I was busy at work in the past months.
There are news, though:
I enhanced Nunit task for CCNET and they accepted my modifications (I will update this post to describe the new behavior),
I will soon post third part of this series,
I’m preparing a new article series about another interesting software.

Thank you for the feedbacks and for the patience to everyone

19 09 2008

Parts one and two have been very helpful in my quest to implement continuous integration. Thank you for making this available in a simple to follow presentation. I am desperately awaiting installment number 3.

Is it possible to use the executable task to delete a directory?

I tried this:

TempFolder /S /Q

but I get an error:
ThoughtWorks.CruiseControl.Core.Tasks.BuilderException: Unable to execute: FileName: [rmdir] — Arguments: [TempFolder /S /Q] — WorkingDirectory: [C:\Continuous Integration\Project]

19 09 2008

oops, my comment had it’s tags removed – that makes it tough to see what I tried to do – I’ll try it again…Here is my <exec> block:

<buildArgs>TempFolder /S /Q</buildArgs>

I hope html encoding it will make it show up properly here 😉

19 09 2008

I figured out how to remove a directory using the executable task:

<buildArgs>/C rmdir TempFolder /S /Q</buildArgs>

19 09 2008

Hello Joel,
I’m happy that you found the solution…sorry for coming back here too late to answer 🙂

9 02 2009

Wish I had found this earlier.
I wasted a lot of time tracking down that NUnit didn’t refresh on failures. 😦
Looked like everything was going great, but the test results weren’t changing.

18 05 2009

Hey ,

thanks a lot for the information.

Could you please mail me all the stuff that you have related to this cruisecontrol ???

Thanking in anticipation


28 09 2009


CruiseControl is there to help us get the work done and you made it easy enough for me to actually save time implementing it. There a cruel lack of documentation for typical uses of ccnet and your article is just great doing that!

Thanks a lot!

4 02 2010


Can you also Include how to integrate FxCop in the CCNet. Hope you’ll include it in your 3rd tutorials.


7 02 2010


I am new to CC.Net and when I tried to setup a project using it, I got errors. Please help me in resolving the error said below.

Full Details:

I am using v1.5 along with tortoise svn v1.6.6 and nunit 2.5.3. Also i have installed dot net framework 3.5 in my system which has XP and iis5.1.

I made a repositry in my local system and its path is like: file:///E:/Websites/Repositry

I have a SVN Checkout folcer in another path like: F:\Test

In my ISS, I have created one more folder with name “Test”, which is a virtual directory to the svn checkout folder.

I am using the below ccnet.config file:


C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe



When I am trying to build the solution using the Force button in, I am getting an error log like the below.

Error Message: ThoughtWorks.CruiseControl.Core.CruiseControlException: Unable to load the output from svn: —> System.Xml.XmlException: Root element is missing. at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.ParseDocumentContent() at System.Xml.XmlTextReaderImpl.Read() at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace) at System.Xml.XmlDocument.Load(XmlReader reader) at System.Xml.XmlDocument.LoadXml(String xml) at ThoughtWorks.CruiseControl.Core.Sourcecontrol.SvnHistoryParser.ReadSvnLogIntoXmlNode(TextReader svnLog) — End of inner exception stack trace — at ThoughtWorks.CruiseControl.Core.Sourcecontrol.SvnHistoryParser.ReadSvnLogIntoXmlNode(TextReader svnLog) at ThoughtWorks.CruiseControl.Core.Sourcecontrol.SvnHistoryParser.Parse(TextReader svnLog, DateTime from, DateTime to) at ThoughtWorks.CruiseControl.Core.Sourcecontrol.ProcessSourceControl.ParseModifications(TextReader reader, DateTime from, DateTime to) at ThoughtWorks.CruiseControl.Core.Sourcecontrol.ProcessSourceControl.ParseModifications(ProcessResult result, DateTime from, DateTime to) at ThoughtWorks.CruiseControl.Core.Sourcecontrol.Svn.GetModifications(IIntegrationResult from, IIntegrationResult to) at ThoughtWorks.CruiseControl.Core.Sourcecontrol.QuietPeriod.GetModifications(ISourceControl sourceControl, IIntegrationResult lastBuild, IIntegrationResult thisBuild) at ThoughtWorks.CruiseControl.Core.IntegrationRunner.GetModifications(IIntegrationResult from, IIntegrationResult to) at ThoughtWorks.CruiseControl.Core.IntegrationRunner.Integrate(IntegrationRequest request)

Pls help me to get rid of this and get a successful build.

Thanks in advance

18 02 2010

Nice Article man but incomplete with the 3rd part,Keenly waiting for that.

6 03 2010

Best article on the subject. Couldn’t wait part 3.

27 04 2010
Anjan Maity


It is very nice tutorial. I have tried out with a solution combine with multiple projects. I am not getting all success.
I am tried with a settings that when a developer commit from a client m/c the ccnet will build automatically. I am not success .Could you be please describe this in part 3 and also please provide some downable source ,


27 06 2010
unit testing

nice one,and also waiting to the 3rd part..
thank u 🙂

2 09 2010

Nice tutorial! I was looking around for some good info like this. Seems a few things have changed in the CC.NET syntax but the overall game is the same. Cheers!

7 10 2010

Good tutorial!

Do you know how to get the patch or .dll for outputproperty of task?

This is there in Ant and whereas it is missing in Nant.

If you know any other way, please let me know.

Thanks in advance,

24 05 2011

Great article!

15 06 2011

Hi Matteo,

This is an excellent and informative article. Thank you very much for posting such a useful article. I learned lot of new things today. Eagerly waiting for part 3.

18 06 2011

Thank you very much for writing such helpful article!

NAnt and CruiseControl.Net have a set of common features. Which tool should we use for those common features? It would be great helpful if you share your idea about this decision.

Thanks in advance.

19 06 2011

I always prefer to use CCNET features when available and rely on Nant or custom executable only when there’s no other chance.
I think that it’s easier to read for a newcomer that need to work with a CCNET instance configured by someone else.
But this is only my personal opinion.

Thank you for you feedback

7 07 2011
Cuong Luc

This is a splendid tutorial which I’m looking for. Thanks for your very nice work!

4 08 2011

This was so useful I am actually wondering how much I’m missing on part 3. Where is it? Please update …

1 11 2011
Ashish Sharma

Excellent Article!
I am trying to setup my server with Cruise Controls and this blog is the best of all. Although, it’s already too late but still I am waiting for Part – 3
Thanks a lot and cheers for this wonderful work.

19 12 2012

There is definately a lot to find out about this issue.
I like all the points you made.

5 02 2013

“CruiseControl.Net Tutorial – Part 2 My view
on C#” ended up being truly compelling and instructive!
Within modern universe that is tricky to accomplish.

I am grateful, Kina

2 03 2013

“CruiseControl.Net Tutorial – Part 2 | My view on C#”
join911truth ended up being a wonderful post.
If only there was significantly more weblogs similar to this excellent one on the cyberspace.
Regardless, thanks a lot for ur precious time, Nan

17 07 2014
Pranjal R Nigam

Thanks for the article.

Many thanks.

16 12 2014
Fix Cruisecontrol Net Configuration Error Windows XP, Vista, 7, 8 [Solved]

[…] CruiseControl.Net Tutorial – Part 2 | My view on C# – Jun 15, 2008 · CruiseControl.Net Tutorial – Part 2 – Matteo continues his series on Cruise Control Setup and configuration with part two, covering the actual build …… […]

1 06 2016

I am using svn as my source control, and its a application, i am using msbuild to build the application.
till here everything is fine, now i want to deploy or copy the only modified files into another directory using ccnet, how can i do this. please help

thanks in advance

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: