Joe in Iowa – A Sandcastle Scenario

This post provides steps to create CHM using Sandcastle. Some of the users have automated these steps. Mikael Söderström has a "Sandcastle Helper" here, Ashley van Gerven has a batch script available here and Scott Hanselman's has power shell script available here. Frank Kroondijk has created a Sandcastle VS 2005 add-in here.

Anders Ljusberg has some interesting finds about Sandcastle here.

Sandcastle installation adds the various tools to your path. Alternatively in the Sandcastle Examples directory, invoke setPath.bat to add the sandcastle tools to your path. Then create a subdirectory for your project and cd into it. Several of the command-line arguments and batch files referenced in the following instructions use relative path expressions that assume this directory structure. You are welcome to use a different directory structure, but if you do so you will need to change those relative path expressions.

In this post I wanted to capture “Joe in Iowa”, an user scenario for Sandcastle and provide some additional details.

Joe in Iowa: “I’m one of four developers on our team creating reusable web controls. We write our own documentation inline using C# XML documentation comments. It’s really convenient and we can see our real documentation in seconds using Sandcastle. Our customers really love the MSDN-like documentation.”

Consider the case of Joe generating documentation for a managed assembly A.dll. Suppose A.dll depends on assemblies B.dll and C.dll. (That is, classes in A.dll inherit from types in B.dll and C.dll, or APIs in A.dll use types in them as parameter and return types.).

The first step in the sandcastle process is to generate reflection data files for the assemblies. To generate a reflection data file for A.dll Joe executes the following command:

MRefBuilder A.dll /dep:B.dll,C.dll /out:reflection.org

Joe can also use wildcards. For example, if Joe’s assemblies to document are in the dll subdirectory and their dependencies are in the dep subdirectory, he can generate reflection data like this:

MRefBuilder dll\*.dll /dep:dep\*.dll /out:reflection.org

The output of MRefBuilder contains information about each API in the reflected assemblies.

If Joe is not sure on which assemblies A.dll depends, he can just go ahead an invoke MRefBuilder with A.dll. If it finds that it needs another one, it will emit an error message identifying the additional dependency assembly that it requires. Joe does not need to provide core .NET Framework assemblies (e.g. mscorlib.dll) that an assembly depends on; MRefBuilder will fetch those from your .NET Framework installation directory.

The reflection information file contains information on each API that MRefBuilder found, but to generate documentation Joe needs a file that contains information on each topic that will appear in his documentation. To generate such a file, Joe needs to apply a few transformations:

XslTransform ..\..\ProductionTransforms\AddOverloads.xsl reflection.org |

XslTransfrom ..\..\ProductionTransforms\AddGuidFilenames.xsl

/out:reflection.xml

These transforms add pseudo-API topics corresponding to overload pages and information about the name of the file in which the topic will be stored. (Why not have MRefBuilder generate this information directly? We wanted to allow the “documentation model” to change without having to change the “reflection step”. If someone decides on documentation model without overloads, or wants to change the file naming convention, that shouldn’t require changing the reflection process.)

The next step in the sandcastle process is to use the reflection data file to generate a manifest of topics to be generated. This is done by applying a transform to the reflection data:

XslTransform ..\..\ProductionTranforms\ReflectionToManifest.xsl reflection.xml /out:manifest.xml

Joe examines the manifest, and notices it is a very simple XML file that lists the ID of each topic to be generated. (If you ever want to build just a handful of topics, it should be easy to construct such a manifest by hand. If you ever develop a complex process that might require you to generate a subset or superset of the topics that this transform produces, it should be a straightforward task to automate the generation of the corresponding manifest.)

Joe is ready to generate topic pages. He needs to create a directory structure to contain them and the associated image, script, and style files. Sandcastle provides a script that creates this structure. Joe executes this script and creates an output directory structure:

..\copyOutput.bat

Now, Joe is ready to generate HTML documentation pages. To do so, he invokes the BuildAssembler tool using the following command:

BuildAssembler /config:..\..\Presentation\configuration\sandcastle.config

manifest.xml

You should see informational messages indicating that BuildAssembler is loading data, then generating topics pages. The output pages will appear in the Output\html subdirectory. Joe opens them in a web browser and peruses the fruits of his labor.

BuildAssembler is the heart of the sandcastle documentation process; all the steps Joe has taken up to now just generate files containing the information that BuildAssembler needs. These files are referenced in the sandcastle.config configuration file.

Packaging: Most documentation is delivered as CHM/HxS files. This section explains how to package the output of the sandcastle tool-chain into such a container. The necessary help compilers are not a part of sandcastle, but are available from:

Microsoft HTML Help 1.x Compiler - The HTML Help Compiler for HTML Help 1.x can be downloaded as part of the Microsoft HTML Help Workshop from msdn.microsoft.com

Microsoft Help 2.0 Compiler - The Help Compiler for Help 2 is part of the Microsoft Visual Studio 2003 .NET Help Integration Kit.

hhc (HTML Help 1.x Compiler):

The CHM compiler hhc.exe requires as input a project (HHP) file and a table of contents (HHC) file. Joe can generate a custom HHP or can copy the HHP template provided by Sandcastle:

copy ..\..\Presentation\chm\test.hhp Output

Joe can execute HHC from the topic data file via a transformation:

XslTransform ..\..\ProductionTransforms\ReflectionToChmContents.xsl

reflection.xml /out:Output\test.hhc

After generating these file, Joe can run the CHM compiler:

cd Output

and then

hhc.exe test.hhp

This creates the file test.chm containing his documentation.

HxComp (Microsoft Help 2.0 Compiler) :

HxComp compiles the Sandcastle target files into an HxS/HxI pair of files. The HxS generation requires a few more project definition files than the CHM case. Sandcastle provides these definition files. Joe begins by executing a script to copy these definition files in to the output directory:

..\copyHavana.bat

Like the CHM case, though, Joe must create file that defines the packaged table of contents (HxT). This is accomplished by a simple transform of the reflection data file.

XslTransform ..\..\ProductionTransforms\ReflectionToHxSContents.xsl reflection.xml /out:Output\test.HxT

Finally, Joe invokes the Help 2.0 compiler to create an HxS file.

cd Output

and then

hxcomp –p test.HxC –l test.log

This creates the file test.hxs containing his documentation.