检查CHM文件中链接的工具

本文介绍了一个用于检查帮助文件(CHM格式)中链接的工具,包括合并文件。该工具可以检查索引、目录和主题文件中的链接,并以树状视图显示结果。

有一个使用XML注释记录的库。使用NDoc生成库参考帮助的CHM文件,但还有一个手写的"主"CHM文件,包含更高层次的帮助。将这两个帮助文件合并,它们都包含彼此的链接。找不到一个工具来检查这些链接,所以写了一个。

这实际上很容易编写,因为它只是一个前端,用于HtmlHelp库和Klaus Weisser的示例查看器。读取CHM文件的所有细节都由库处理,这意味着所要做的就是编写UI和检查算法。

基本上,如果需要这个工具,它将是无价的;如果不需要,那么感谢关注。

使用应用程序

应用程序非常容易使用 - 至少尝试让它变得简单。

首先要做的就是打开一个CHM文件。这会将文件和任何合并的文件加载到库中,并开始填充结果树。可以随时刷新文件以回到这个状态。在这个阶段,索引、目录和主题文件都存在,但主题文件中的链接不存在。

事实证明,从HTML文件中获取链接并不那么容易。在MSDN上找到的唯一相关文章是:C#中访问DHTML DOM的教程。这基本上说打开一个IE窗口,加载文件,然后从DOM中获取链接。这很慢。如果CHM文件有成千上万的页面,这非常慢。然而,这是最准确的方法,因此是默认的。

可以通过在工具栏上选择"快速解析"选项来将速度提高几个数量级。这使用正则表达式搜索原始HTML。这对简单的HTML效果很好,但并不完美,尽管它现在排除了注释块。它作为第一次尝试很有用,但建议在发布帮助文件之前使用慢方法进行检查。

现在已经选择了解析方法,可以通过点击"工作"工具栏按钮或按Ctrl+W开始检查。这个过程加载并解析所有主题文件,并检查找到的所有链接。这个过程在树视图中选定的子树上工作。默认情况下,根节点被选中,所以整个帮助集合被检查,但如果只对那个分支感兴趣,可以选定树的一部分。结果通过设置每个树视图项的图标显示。

结果中的每个项都有一个状态,可以是"未知"、"良好"、"http"、"脚本"或"损坏"。父项的状态根据其子项的状态设置。所以,只有当它的子项没有被标记为损坏时,父项才被标记为良好。这可以快速让了解链接的正确性,详细的指标显示在每个项后的括号中。

然后可以使用包括正则表达式在内的全面查找功能导航结果:

还可以将结果导出到CSV文件。这会产生一个总体摘要文件,以及每个CHM的一个详细信息文件。

所有这些都可以通过命令行选项自动化。这些是:

-f / -fast: 选择快速模式 -s / -slow: 选择慢速模式 -o / -open: 打开最近使用的CHM -o:"C:\path\xxx.chm": 打开指定的CHM -w / -work: 检查文件 -x / -export: 将报告导出到默认文件夹 -x:"C:\path\folder": 导出到指定文件夹 -c / -close: 关闭应用程序

所以一个例子可能是:

CheckHelpLinks.exe -f -o:"C:\test\test.chm" -w -x -c

应用程序的退出代码为零表示没有错误,非零表示有损坏的链接。

就是这样。去修复损坏的链接,然后再检查一次!

感兴趣的点

反射魔法

需要访问库中声明为internal的属性。显然,这通常在库外部不可用,但可以使用反射来访问它。这是一个非常强大的实践,但并不理想:库作者完全有权在未来的版本中更改他的内部实现,这将破坏客户端代码。所以,自担风险使用!

这段代码来自ClassesIndex.cs文件中的IndexItem.Load方法。

想写的是:

C# CHMFile chmFile = indexItem.ChmFile;

实际写的是:

C# Type t = indexItem.GetType(); PropertyInfo p = t.GetProperty( " ChmFile" , BindingFlags.Instance | BindingFlags.NonPublic ); CHMFile chmFile = ( CHMFile ) p.GetValue( indexItem, null );

访问DHTML DOM

发现访问DOM的唯一方法是打开一个Web浏览器控件,加载HTML,然后从控件的Document属性中获取IHTMLDocument2对象。除了慢之外,这有点棘手,因为加载过程是异步的。通过在开始导航之前设置一个标志,并等待DocumentComplete事件处理程序清除该标志来解决这个问题。在等待期间,调用Application.DoEvents以保持UI新鲜。不知道这有多好,因为这一切都发生在一个对话框中;真正想要的是运行对话框的消息循环,但找不到这样做的方法:(。代码在DlgBrowser.cs文件中,如果想看看。

正则表达式

这些是在快速模式下使用的RegEx。有两个RegEx用于锚点和链接,分别寻找有和没有引号的元素:

Comment: ^(?.*)(?)(?.*)$ Anchor 1: <\s*A\s[^>]*name\s*=\s*(?[^'"].*?)[\s>] Anchor 2: <\s*A\s[^>]*name\s*=\s*(?['"])(?.*?)\k Link 1: <\s*(?:A|AREA)\s[^>]*href\s*=\s*(?[^'"].*?)[\s>] Link 2: <\s*(?:A|AREA)\s[^>]*href\s*=\s*(?['"])(?.*?)\k
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485