Wednesday, February 11, 2009

Using Sandcastle with CruiseControl.NET

For a new project at work, I'm adding automatically-generated API documentation as part of my nightly build. Back in the days of .NET 1.1, we had the NDoc project, and explicit support for it in NAnt. Unfortunately, the project never made the transition to .NET 2.0, instead coming to a rather bitter and public end due to predominantly a lack of community support (despite the large numbers of downloads). I guess it's one the main failing of open-source projects - many are happy to take, but not so happy to give (whether money or time/effort).

Sandcastle is Microsoft's official documentation generator, but even three years on, it lacks some of the user-friendliness that any NDoc user had come to expect. The Sandcastle Help File Builder tool goes a long way to rectifying this, but most of the focus is on the GUI tool. Until the current v1.8 release, command line builds were taken care of by the SandcastleBuilderConsole.exe tool; however, the latest release drops this, and instead uses MSBuild, which ships with the .NET Framework. This is a rather nice touch, in my opinion - a clever use of existing tooling, rather than writing another new tool.

However, the documentation about using it in a continuous integration environment is still a little lacking, so I'm documenting here the problems I came up against.


So far, it seems like neither Sandcastle nor SHFB have been designed with easy deployment in mind. I like to include my build tools within my source repository; this saves a lot of tedious installation and configuration whenever setting up a new developer PC. Both tools come as MSI packages, with Sandcastle deploying as a 220Mb install, so maybe that one you can do without in your repository! SHFB on the other hand is relatively lightweight, at around 3Mb for the files required by the build tasks. You will need to set an environment variable for it to run properly, though:

<setenv name="SHFBROOT" 
   verbose="true" />

The SHFB files that you seem to require are:

  • ColorizerLibrary.dll;
  • ICSharpCode.TextEditor.dll;
  • SandcastleBuilder.Components.Config;
  • SandcastleBuilder.*.dll;
  • SandcastleHelpFileBuilder.targets;

You'll also need the Help 2.0 Compiler tool hxcomp.exe, which ships as part of Visual Studio 2008 SDK; and of course, the SDK requires that Visual Studio 2008 is installed before it itself will install. Fortunately, you can pull out the contents of C:\Program Files\Common Files\Microsoft Shared\Help 2.0 Compiler\ and add that to your repository as well, bypassing that little pain-in-the-neck.


To use SHFB within CC.NET with NAnt, you'll need the <msbuild> task that comes with NAntContrib. The syntax is as follows:

<msbuild project="${source.basedir}\Documentation.shfbproj">
   <arg value="/property:${HxComp.dir}" />
   <arg value="/property:SandcastlePath=C:\Program%20Files\Sandcastle\" />

All the properties listed in the SHFB GUI tool can be set as above - just watch out for the need to escape spaces when hard-coding paths, which had me stumbled for an hour or two, until I found a post asking the same question.

Still To-Do

The one thing I really want to get done is programatically set the assemblies which will be documented; at the moment, you either use the GUI tool and relative paths, or edit the SHFB project file by hand. You could probably also use NAnt's <xmlpoke /> task to edit it, but I would prefer to be able to set it via parameters to the <msbuild /> task, so watch this space while I work it out.


Unknown said...

Nice job :)

Actually I did almost the same. Instead of using the MsBuild task I'm using an exec task and supplying the assemblies to document as command line parameters. This can be set up in a pretty generic way.

But ... I still have a problem. It was all working fine until I put the stuff into svn. During compilation SHFB will copy the "icons", "scripts" and "styles" directories from the sandcastle folter to the output folder ... along with the ".svn" subfolders and stopped compiling the help project. Did you maybe encounter something like this as well? Maybe also have a solution?

David Keaveny said...

Are you saying that you put the documentation into SVN? I can see that as being more trouble than it's worth, much better to upload it to a webserver or other central location after (e.g. using a BuildPublisher in CC.NET).