1

I want to produce a number of separate output CHM files (for separate libraries, so I have a separate shfbproj for each), but that have a number of conceptual topics in common.

I would like to be able to put the .aml files for these topics in one place and then import them into each of the projects, to avoid duplication.

Ideally, I'd like to have a common .content file in this central location as well, and import this as children of a specific parent topic node in the "real" project's .content file, to avoid duplicating that too.

Is there any way to do this? Trying to add existing files to the project results in either creating copies of the files, or making the project unloadable if manually edited to point at files outside of the project's folder.

(I also tried making a shfbproj for the common content and then referencing this in the "real" project, but this appears to have no effect.)

help-info.de
  • 6,695
  • 16
  • 39
  • 41
Miral
  • 12,637
  • 4
  • 53
  • 93

2 Answers2

1

A solution depends heavily on your requirements and the intended structure of your generated help file. Using the Visual Studio Add-In and the stand-alone Sandcastle Help File Builder (SHFB) GUI is different.

As you can see in the CHM screenshot there is a Glossary topic above my BMI class documentation. This topic is not in the project, but in another directory.

CHM help file

Help file builder projects support linked items as well. Linked items are files that appear in the current project's folder structure but are physically located in a location outside of the current project's folder structure. An example would be sharing a token file between multiple projects. If the file is edited in one project, those changes are reflected in the other projects in which it is a linked or actual item when those projects are built.

Linked Items can be added in Visual Studio in the usual manner. Select the option to add an existing item and in the file selection dialog box, rather than clicking the Add button, click the drop down arrow on it and select the Add as Link option (as shown below).

Screenshot of Solution Explorer and add item dialog

I think this is a possibility for your additional content.

As a next step you need to double click your e.g. ContentLayout.content file and edit the structure manually.

enter image description here

Additional Info quoted from Sandcastle Help File Builder Documentation:

If you do not have Visual Studio, the only way to create linked items is by manually editing the project in a text editor. To do so, add a build item to an item group. This is done by adding an element named after the build action (i.e. Tokens for a token file). The Include attribute points to the relative path of the file which is typically outside of the current project's folder structure. Add a Link element nested within the build item and set its property value to the relative path of the item within the current help file builder project. For example:

<Tokens Include="..\SomeOtherProject\Tokens\SharedTokensFile.tokens">
  <Link>Tokens\SharedTokens.tokens</Link>
</Tokens>

The example above creates a linked tokens file. Its physical location is one level up from the help file builder project folder in another project folder (..\SomeOtherProject\Tokens). Its virtual location within the current project will be in a folder called .\Tokens.

Linked items will have a Remove option rather than a Delete option. This removes them from the project but leaves them on disk in their original location since they may belong to another project.

help-info.de
  • 6,695
  • 16
  • 39
  • 41
1

Ok, there are a couple of tricks to get this to work as desired; thanks to help-info.de's answer for inspiration on the Link elements.

Firstly, in the common docs folder, create CommonDoc.targets:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <ItemGroup>
        <Folder Include="common\" />
    </ItemGroup>
    <ItemGroup>
        <ContentLayout Include="$(CommonContentDir)100-common.content">
            <Link>common\100-common.content</Link>
        </ContentLayout>
    </ItemGroup>
    <ItemGroup>
        <None Include="$(CommonContentDir)performance.aml">
            <Link>common\performance.aml</Link>
        </None>
        <None Include="$(CommonContentDir)security.aml">
            <Link>common\security.aml</Link>
        </None>
    </ItemGroup>
</Project>

Next, edit the main shfbproj file and add the following below the existing PropertyGroup elements:

<PropertyGroup>
    <CommonContentDir>..\..\Doc\</CommonContentDir>
</PropertyGroup>

This is the relative path from the folder with the shfbproj to the common docs folder.

Also add the following just above the existing Import element:

<Import Project="$(CommonContentDir)CommonDoc.targets" />

And finally (this part you can do in the GUI), split the existing .content files up into multiple files such that anything you want to appear before the common content is named with a number lower than 100 and anything afterwards with a number higher than 100. (Apparently multiple content files are sorted alphabetically before merging.)

(You can use a different number for the common content if most of the content will normally be added before it, but for my case it was the other way around.)


The CommonContentDir property is mildly annoying; I wanted to use $(MSBuildThisProjectDir), but it appears that the SHFB build doesn't recognise this and tries to find the files in the main shfbproj's folder instead.

Another downside of this method is that when you want to add a new file to the common topics, you will have to edit the CommonDoc.targets file manually. But once you do that, it will automatically appear in every help file that references that file, without having to update each shfbproj individually.

Miral
  • 12,637
  • 4
  • 53
  • 93