原文地址:http://broadcast.oreilly.com/2010/09/build-html-documentation-for-y.html#comments
Sandcastle 功能概述
如果您使用过的程序集中,带有详细的 API 说明文档,并且文档的格式和 MSDN 上的一样,您将发现这样 API 说明文档的是多么的方便。生成类似的 HTML 格式文档的方法有很多,不过,我发现其中最简单的方法是使用 Sandcastle 工具来生成这样的 API 文档。Sandcastle 是微软开发的一款开源的文档生成器,它可以读取您的程序集(DLL 和 EXE 文件)和 XML 注释文件,而且能自动生成相应的 HTML 格式的文档。Sandcastle 既是一款非常灵活的工具,同时它也是一款非常复杂的工具。不过幸运的是,还有另外一款与之类似的辅助工具, Sandcastle Help File Builder,这个工具让您在几分钟之内就可以很容易地获取和运行 Sandcastle。
本教程将带您创建简单的 HTML 格式的类描述文档,下面是我们接下来要做的:
- 步骤一: 安装 Sandcastle 和 Sandcastle Help File Builder
- 步骤二: 创建一个名称为 Guy.cs 的 C# 代码文件
- 步骤三: 把 C# 代码编译成 Guy.dll 程序集
- 步骤四: 安装 Sandcastle Help File Builder 项目
- 步骤五: 运行 Sandcastle
备注,我们还需完成一些额外的事情:
- 5.1 修复复 Sandcastle
[丢失 <summary> 节点]
的问题 - 5.2 添加一个 AssemblyInfo.cs 文件来设置程序集属性
- 5.3 运用 MSBuild 从控制台命令行来运行 Sandcastle 的项目文件
- 5.4 在 Visual Studio 项目中运用 Sandcastle Help File Builder 项目
步骤一: 安装 Sandcastle 和 Sandcastle Help File Builder
Sandcastle 是一款非常强大、灵活的工具。由于它是基于控制台命令行的,因此没有相应的图形界面终端可供使用。这样您就很难随意启动并使用它就。和其他大部分软件一样,Sandcastle 也满足 80/20 规则 : 80% 的用户仅仅使用其中 20% 的功能。幸运的是,现在有一个名称为 Sandcastle Help File Builder 的工具,它让您非常方便地使用 20% 的功能。有了 Sandcastle 和 Sandcastle Help File Builder (有时把它简称为缩写形式 SHFB),您几分钟内就可以启动并生成辅助文件和 HTML 文档了。
首先下载和安装 Sandcastle and Sandcastle Help File Builder(这里我用的是 2015.1.12.0版本):
- 使用下载链接 Sandcastle CodePlex 页面 来下载和运行最新的稳定版的安装程序
- 对 Sandcastle Help File Builder 做相同的操作
- 确保您注意到了 Sandcastle 和 Sandcastle Help File Builder 的安装目录。这里将它们被安装在以下路径 D:Program Files 或者 D:Program Files(x86)— Sandcastle 被安装在名称为 Sandcastle 文件夹
下,
SHFB 被安装在 EWSoftwareSandcastle Help File Builder 文件路径下。
注意,安装 Sandcastle 和 Sandcastle Help File Builder 后,您还可以把它们安装目录下面的内容全部复制到另外一个目录下,从而把它们的安装路径改成你想要的路径,在新目录下,它们依然可以被启动并使用。如果您工作的机器被锁住,您不能用它来安装程序 — 为了安全,办公室里的很多电脑都会被锁住 — 这个功能将很有用。当您在一个构建服务器上运行一个连续的生成命令,来生成 HTML 文档,但是您又没有管理员权限时,它也可以派上用场。
步骤二: 创建一个名称为 Guy.cs 的 C# 代码文件
Sandcastle 按两步来生成文档。 第一步,利用反射来检查程序集中的公共类中的成员,第二步,读取 XML 注释文档并生成的相关记录。
当 Sandcastle 从程序集中创建文档时,它需要程序集中至少有一个命名空间和并且命名空间中至少包含一个公共的类。否则,它将抛出一个错误(我们将在几分钟内看到)。因此,我们需要做的第一件事是准备好您的代码,并添加 XML 注释。
(如果您之前没有使用过 XML 注释,您可以在我的 C# XML 注释教程 中快速的浏览它们。同样,如果您对 .NET 程序集和 C# 命名空间比较迷惑,浏览一下我的 C# 与 .NET 程序集和命名空间教程 。)
在本教程的第一部分, 我们将在控制台命令提示行中完成所有后台任务。所以现在,您应该使用 Notepad 来编码我们创建的源文件。在命令行中执行所有后台命令和在 Visual Studio 执行时的效果一样。我比较担心控制台命令行,因为这里使用的是手动构建工具,所有我们需要知道如何创建文件。而且在构建过程中,还需要在控制台命令窗口中使用一些控制台命令,然而许多 .NET 开发人员使用控制台命令提示符的时间并不长。如果您没有使用过,也不用担心,您只需看看网上的这个章节 从命令提示符中编译和运行 C# 代码。
我已经准备了一个带有 XML 注释的类。它在我的 我的简单工具类 Guy。前往并 从该链接中复制 Guy.cs 的代码 ,把它粘贴到 Notepad,,最后将其保存文名称为 Guy.cs 的文件。
下面是 Guy 类的代码:
/// <summary> /// 一个伙计,拥有名称,年龄和装满现金的钱包 /// </summary> class Guy { /// <summary> /// 为 Name 属性创建的支持只读的字段 /// </summary> private readonly string name; /// <summary> /// 伙计的名称 /// </summary> public string Name { get { return name; } } /// <summary> /// 为 age 属性创建的支持只读的字段 /// </summary> private readonly int age; /// <summary> /// 伙计的年龄 /// </summary> public int Age { get { return age; } } /// <summary> /// 伙计拥有的现金 /// </summary> public int Cash { get; private set; } /// <summary> /// 构造方法,用来设置名称,年龄和现金 /// </summary> /// <param name="name">伙计的名称</param> /// <param name="age">伙计的年龄</param> /// <param name="cash">伙计最初拥有的现金</param> public Guy(string name, int age, int cash) { this.name = name; this.age = age; Cash = cash; } public override string ToString() { return String.Format("{0} 今年 {1} 岁,而且拥有 {2} 元现金", Name, Age, Cash); } /// <summary> /// 从伙计的钱包中捐钱 /// </summary> /// <param name="amount">打算捐的现金数目</param> /// <returns>实际捐出的现金的数目,如果钱包中的钱不够就返回 0</returns> public int GiveCash(int amount) { if (amount <= Cash && amount > 0) { Cash -= amount; return amount; } else { return 0; } } /// <summary> /// 向钱包中存入一些现金 /// </summary> /// <param name="amount">打算存入的现金的数目</param> /// <returns>实际存入的现金的数目,如果没有存入现金就返回 0</returns> public int ReceiveCash(int amount) { if (amount > 0) { if (amount > 0) { Cash += amount; return amount; } Console.WriteLine("{0} 说:{1} 不是我将拿走的数目", Name, amount); } return 0; } }
注意 Guy 类是如何利用 String 类和 Console 类的?它们都是 System 命名空间下的一部分,因此为了避免编译出错,需要 在 Guy.cs 文件的顶部添加这一行:
using System;
您的代码现在可以准备去编译了。(您可能已经发现了一个小小的错误,这个错误将使 Sandcastle 出现问题 — 我们将在几分钟内修复它)
步骤三: 把 C# 代码编译成 Guy.dll 程序集
现在我们开始使用 C# 编译器的控制台命令 CSC 命令来编译代码。下面介绍怎么来执行它:
%SystemRoot%Microsoft.NETFrameworkv4.0.30319csc.exe
如果你得到一个 "系统找不到指定的路径 " 的错误, 在命令行中用 v3.5 替换 v4.0.30319
. 本教程中的一切程序都是在 .NET 3.5 下运行的。 v4.0.30319 表示 .Net Framework 4.0 的版本号。本教程中所有的工作都可以在 .NET 3.5 中成功运行,所以如果你已经安装了它,你可以把 v4.0.30319 替换成 v3.5后再运行。 或者,如果你已经安装了 Visual Studio ,你可以启动 Visual Studio 的控制台命令,csc.exe 命名就在对应的目录下。(Express 版本的 Visual Studio没有此功能)
打开命令行提示符并把目录指向你保存 Guy.cs 文件的地方,运行下面的命令:
%SystemRoot%Microsoft.NETFrameworkv4.0.30319csc.exe /target:library /doc:Guy.xml Guy.cs
控制台将显示的以下界面 (我的 Guy.cs 文件保存在 F: empGuy):
当你运行 csc.exe,它会新建两个文件: Guy.dll (包含 Guy 类的程序集)和 Guy.xml (包含从 XML 注释中生成的文档)。
步骤四: 设置 Sandcastle Help File Builder 项目
为了运行 Sandcastle Help File Builder,你只需要设置几个变量然后运行 SandcasteBuilder 的图形界面。最简单的方法就是复制下面三个命令到控制台命令行:
set DXROOT = F:Program Files (x86)Sandcastle set SHFBROOT = F:Program Files (x86)EWSoftwareSandcastle Help File Builder set LANGUAGE = "%SHFBROOT%SandcastleBuilderGUI.exe"
(您可以按以下方式在控制台窗口中使用粘贴功能:点击窗口左上角的菜单图标,并选择编辑 >> 粘贴)
打开 Sandcastle Help File Builder 的操作界面,在菜单中选择文件 >> 新建项目,并命名为 Guy.shfbproj (这是 SHFB 项目通用的扩展名)。下面是新建 SHFB 时的操作界面:
接下来,你需要告诉 SHFB 从哪里去找 DLL and XML 文件,来给 Sandcastle 使用并生成相关文档。先在项目资料管理器中,右击“文档”,选择 "添加文档源...", 导航到 Guy.dll 文件并选中它,SHFB 会自动一并添加 XML 文件 — 需要把 Guy.dll 和 Guy.xml 都添加到文档源中:
如果您正在使用的 dll 文件中包含对其他 dll 文件的引用,您可以通过资源管理器中的引用节点来添加对它们的引用。就像在 Visual Studio 中添加引用一样来添加对它们的引用。
接下来,您将选择输出格式。默认地,Sandcastle 会生成一个 HTML 辅助文档 CHM。 在 Build 选项卡下找到 Help File Formats 下拉框,去除 HtmlHelp1 的选中,然后勾选 Website:
您也可以使用 HtmlHelp1 选项来生成一个 HTML 帮助(*.chm后缀)文件。但是在您使用之前,您需要安装 Html Help 1.x SDK。查阅 HTML Help MSDN page 可以获取更多的信息和下载链接。
点击工具栏上的 “保存所有” 按钮来保存 Guy.shfbproj 项目。现在,您的 Sandcastle Help File Builder 项目就准备好了。
步骤五: 运行 Sandcastle
下面将运行 Sandcastle。在其菜单中选择 >> 生成文档 来运行 Sandcastle。在生成输出标签中,您会看到 Sandcastle 的运行状态:
噢,您好像得到了一个错误!
SHFB: Error BE0033: No APIs found to document. See error topic in help file for details.
记住我之前怎么说的,您的程序集必须至少包含一个命名空间和一个公共类。而程序集 Guy.dll 都没有包含。
幸运的是,这很容易修改。在 Notepad 中打开 Guy.cs 并做如下改动 。您将使用 namespace
关键字来把类 Guy 存放到名称为 GuyTest 的命名空间中,同时您将使用
public关键字来使类 Guy 变成公共访问类 — 保证您在类定义末尾处添加了一个关闭的花括号!下面是定义好的类和命名空间(新添加的文本用 粗体 表示)
using System; namespace GuyTest { /// <summary> /// 一个伙计,拥有名称,年龄和一个装满现金的钱包 /// </summary> public class Guy { ... existing Guy class ... } }
既然 Guy 类已经是公共的并在 GuyTest 命名空间中,您就可以编译程序集了。再次运行 CSC 命令来重新生成 Guy.dll 程序集。 这次应该重写 Guy.dll 程序集和 Guy.xml 文件。
这次 CSC 命名会给出一个缺失 XML 注释的警告,但也会运行:
F: empGuy>%SystemRoot%Microsoft.NETFrameworkv4.0.30319csc.exe /target:library /doc:Guy.xml Guy.cs Microsoft(R) Visual C# 编译器版本 4.6.1055.0 用于 Microsoft(R) .NET Framework 4.5 版权所有 (C) Microsoft Corporation。保留所有权利。 Guy.cs(61,25): warning CS1591: 缺少对公共可见类型或成员“Guy.ToString()”的 XML 注释
我们将在几分钟内修复这个问题。但是首先 使用文档 >> 生成项目并再次运行 Sandcastle。 这次生成将会非常成功:
祝贺您 — 现在您已经成功生成了 HTML API 文档!在IE浏览器中打开帮助文档 Helpindex.html。
在页面的顶端,您会得到一个警告信息:
点击它并从菜单中选择“允许阻止的内容...”,这样做后,您将会看到新生成的 HTML 帮助文档!
5.1 修复 Sandcastle [丢失 <summary> 节点]的问题
您可能已经注意到生成的 HTML 帮助页面中,有一个这样的标题: A Sandcastle Documented Class Library 。可以修改这个标题,返回到项目属性页并修改帮助标题属性。 确保最后您保存了 SHFB project file 文件。
接下来,您还记得执行 CSC 命令时,显示的缺失 XML 注释的警告吗?
Guy.cs(47,29): warning CS1591: Missing XML comment for publicly visible type or member 'GuyTest.Guy.ToString()'
在 IE 浏览器中找到 HTML 帮助,并导航到 GuyTest 命名空间 >> Guy 类 >> Guy 方法 >> ToString 方法。您将看到这个:
这是 Sandcastle 生成的提示信息,因为它找不到相关的注释。您可以通过为 ToString() 方法添加一个 XML 注释来修复这个问题。为上面的 ToString() 方法,添加这样的注释:
/// <summary> /// ToString()方法返回 guy 对象的名称,年龄和现金 /// </summary>
/// <returns>伙计的基本信息</returns> public override string ToString() { return String.Format("{0} is {1} years old and has {2} bucks", Name, Age, Cash); }
5.2 添加一个 AssemblyInfo.cs 文件来设置程序集属性
最后,点击 Guy 类的任意一个成员,您将看到下面这行说明:
Assembly: Guy (in Guy.dll) Version: 0.0.0.0
您可以创建一个 AssemblyInfo 文件来改变版本号。它和 Visual Studio 生成的典型的属性文件一样。下面是 Guy 类的一个属性文件的例子 — 我用 Visual Studio 先新建一个新项目然后来创建它,但是您只能 把它粘贴到 Notepad 并保存为 AssemblyInfo.cs 文件:
AssemblyInfo.cs:
using System.Reflection; using System.Runtime.InteropServices; // 有关程序集的常规信息通过以下 // 特性集控制。更改这些特性值可修改 // 与程序集关联的信息。 [assembly: AssemblyTitle("ConsoleApplication")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("ConsoleApplication")] [assembly: AssemblyCopyright("Copyright © Microsoft 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 使此程序集中的类型 // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, // 则将该类型上的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("45cc3d18-1e80-4154-9c84-bfa454656022")] // 程序集的版本信息由下面四个值组成: // // 主版本 // 次版本 // 生成号 // 修订号 // // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, // 方法是按如下所示使用“*”: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
现在您可以 使用 CSC 命令重新编译程序,这次添加 AssemblyInfo.cs 到命令行的末尾。 下面是控制台命令行代码:
%SystemRoot%Microsoft.NETFrameworkv4.0.30319csc.exe /target:library /doc:Guy.xml Guy.cs AssemblyInfo.cs
在您的文件资源管理器中右击 Guy.dll 并选择 Properties,点击“详细信息”标签,您将看到新的版本号,标题,公司和版权。
回到生成的 HTML 帮助页面,在左边的文件树节点里点击(“GuyTest Namespace”)节点。注意:它又产生了一个相似的错误:
[缺失 "
N:GuyTest" 文档]
XML 注释在命名空间中无效,请不要相信我之前说过的话 — 尝试在命名空间上添加一个 <summary> 注释并重新编译您的代码。否则您将得到下面的警告:
警告 CS1587: XML 注释没有被放置在一个正确的语言元素下
您的 DLL 和 XML 文件将像以往一样被生成,但是 XML 文件将不会对命名空间的进行注释。
幸运的是,这钟事情在 Sandcastle 中很容易处理。回到项目“属性”页并在注释部分点击 "Summaries" 选项。点击“Edit Namespace Summaries”按钮,将弹出命名空间注释窗口。在窗口中的 "Checked namespaces" 选项盒中,点击 GuyTest 命名空间来选中它,并确保它被选中,同时也选中它的上面是"(global)"选项。然后确保右边的"Selected namespace appears in"窗口中的 Guy 被选中。然后在下面的大的文本框中输入一个注释。
关闭命名空间概要窗体。现在命名空间概要属性将读取:1 显示概要,0 从项目中排除。
点击工具栏上的全部保存按钮并重新生成文档。当您在 IE 浏览器中重新加载它时,您将看到命名空间和 ToString() 方法的概要。
5.3 运用 MSBuild 从控制台命令行来运行 Sandcastle 的项目文件
当您的 SHFB(*.shfbproj) 项目文件可以正常运行后,您还可以在控制台命令行中使用 MSBuild 命名来生成它。 这是用于 Visual Studio 的代码生成器。和用来编译 C# 的 CSC 命令 一样,它和 .NET Framework 一起被安装。同时您需要运行下面的命令来生成 Guy 类的说明文档:
%SystemRoot%Microsoft.NETFrameworkv4.0.30319msbuild.exe Guy.shfbproj
等等 — 您得到下面的错误了吗?
错误 MSB4019: 未找到导入的项目 "C:SandcastleHelpFileBuilder.targets"。请确保申明的路径正确,并且该文件在磁盘上存在。
如果您得到了这个错误,确保 DXROOT, SHFBROOT, 和 LANGUAGE 变量都被设置好了。如果您不设置 SHFBROOT 变量,您将得到这样的信息。同样如果您不设置 DXROOT 变量 SHFB 将找不到 Sandcastle。因此,如果这些环境变量没有被设置时,您可能需要去 再次执行这三个设置控制台的命名 (在运行 SHFB 之前您已经执行过的相同的命令)。
下面是我运行后的界面:
用 MSBuild 命令生成的文档和上面用 CSC 命令生成的文档完全一样。如果您需要把文档整合到一个持续生成的环境中,MSBuild 命令将非常有用。
是否得到一个警告 (SHFB : 警告 BHT0001
)? 如果您得到了,这个问题已在一些 SHFB 版本中被发现。您可以使用 MSBuild 3.5 命令来阻止这个警告 而不是 4.0.x。在大多数情况下,SHFB 和 Sandcastle 仍然可以很好地生成文档,即时产出了这个警告。获取更多信息,请查看 SHFB Codeplex 站点上的这个线程。
5.4 在 Visual Studio 项目中运用 Sandcastle Help File Builder项目
Sandcastle Help File 生成器也可以使用 C# 项目文件(*.csproj)作为一个文档源。下面将介绍如何获取您的 Guy.cs 文件和 AssemblyInfo.cs 文件,并把它们添加到 Visual Studio 的一个类库中,然后从这个项目中,利用 Sandcastle Help File Builder 来生成文档。
首先,创建一个新的 Visual Studio 项目并添加 Guy.cs 和 AssemblyInfo.cs 文件:
- 启动 Visual Studio 并 创建一个新的名称为 GuyTest 的类库 (GuyTest.csproj)
- 删除 Visual Studio 自动为您添加的 Class1.cs文件
- 在资源管理器中右击 GuyTest 并添加一个已存在的项目到您的工程中。导航到 Guy.cs 文件并添加它
- 在资源管理器中展开“属性”文件夹并删除 AssemblyInfo.cs 文件
- 添加另外一个存在的项目到您的工程 — 这次导航到 AssemblyInfo.cs,把它拖动到项目的“属性”文件夹下,然后包含到项目中
还有另外一件事您需要做。 在解决方案资源管理器中,右击 GuyTest 并在菜单栏中选择属性 打开项目属性页。点击“生成”标签,并 选中“ XML 文档文件”这个的复选框。 指定其文件名为 Guy.xml。
点击工具栏上的全部保存按钮来保存您的项目。现在这个项目生成的 Guy.dll 和 Guy.xml 文件和您之前用 CSC 命名生成的文件一样。不仅如此,如果您需要,您还可以在控制台命令窗口使用 MSBuild 命令来编译它 — 只需要传递一个 GuyTest.csproj 参数。
现在回到 Sandcastle Help File 生成器,在文档源目录下右击 Guy.dll ,并选择从菜单中移除。 然后对 Guy.xml 做一样的操作。
最后, 添加 GuyTest.csproj 到文档源目录下, 它在 Visual Studio 为您创建的文件夹下。点击工具栏上的全部保存按钮来保存 GuyTest.shfbproj。
现在您可以重新运行 Sandcastle,或者使用 Sandcastle Help File Builder 或者 MSBuild。这次,它将生成相同的文档,但是它是利用 .csproj 文件而不是您使用 CSC 命令生成的 DLL and XML 文件。
首先,您需要生成 DLL。您可以在 Visual Studio 进行生成 — 或者,如果您需要,您也可以不用 Visual Studio 来生成,而是用 MSBuild 命令进行生成。下面是我使用 MSBuild 命令来生成 DLL 时的代码。这里需要传递 GuyTest.csproj 文件的完整路径给 MSBuild 命令。注意:请确保您指定的路径是正确的!同时如果有任何空格,请用引号 "" 把它们包括起来。
F: empGuy>%SystemRoot%Microsoft.NETFrameworkv4.0.30319msbuild.exe "F:ProjectsConsoleApplicationGuyTestGuyTest.csproj"
生成的文件如下:
接着我使用 MSBuild 重新编译 GuyTest.shfbproj 。生成的 HTML 文档和上面的一样,不过,这次我使用的文件源是 C# 的类库项目文件。
作者介绍:
Andrew Stellman 是《 Head First C# 》一书的作者,在 O'Reilly 出版社还出版过其他书籍。了解更多关于 Andrew 的信息请打开 Building Better Software。