This project has moved and is read-only. For the latest updates, please go here.

Custom reference links to an external site

Topics: Developer Forum
Mar 26, 2012 at 8:24 PM
Edited Mar 26, 2012 at 10:18 PM

Hello everyone,

I've been happily using SHFB for quite some time to document our projects, some of which make heavy use of external third-party libraries. The vendor of these libraries provides documentation for their APIs online. I would like to include links to their online API reference website in my generated documentation whenever a .NET type from their library occurs in my project. Very much like the standard MSDN links, except not for MSDN.

Given that I am able to resolve a type to an URL on the external website, could you please give me some pointers as to where do I start? What (plugin, interfaces etc.) needs to be implemented?

Thank you very much for your effort,


Mar 27, 2012 at 3:34 AM

A build component that runs in the BuildAssembler step would be the best solution in this case.  You could probably model it after the ResolveReferenceLinksComponent2 in Sandcastle although it would be simpler as it wouldn't have to resolve the links via a web service.  Yours would probably have to run just before it in the configuration file so that you could extract and resolve reference links that you are interested in before the standard component resolves and removes them.  I wrote an article on CodeProject about creating a build component.  It's a little dated but still fairly relevant.  You can find it here:

Take a look at the SHFB help file for information on creating a component configuration file so that you can integrate it into the SHFB project using the ComponentConfigurations project property:



Mar 27, 2012 at 10:08 PM
Edited Mar 27, 2012 at 10:12 PM

Thank you Eric for your quick reply.

I went through the references docs and tried to implement a build component skeleton and include it in the build process. The implementation is very simple at this point:


    public class MyComponent : BuildComponent
        public MyComponent(BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration)
            MessageBox.Show("constructor called");

        #region Overrides of BuildComponent

        public override void Apply(XmlDocument document, string key)


Then I added the following build component configuration file (running Win7 x64):
C:\ProgramData\EWSoftware\Sandcastle Help File Builder\Components and Plug-Ins\MyComponent.components)

xml version="1.0" encoding="utf-8"?> <components> <component id="Custom Website Reference Links" type="MyBuildComponent.MyComponent" assembly="D:\dev\EsriDocs\TestSolution\MyBuildComponent\bin\Debug\MyBuildComponent.dll"> <description>This build component can use custom links.</description> <configureMethod name="-" /> <insert placement="before" type="Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2" /> <insertConceptual placement="before" type="Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2" /> </component> </components>


Please note that this is meant as a preliminary test, hence the absolute path to my assembly.

Now, I know that the configuration file is picked up by the SHFB UI because my component appears in the list of build components to include in the build process. However, when enabled, SHFB is unable to merge my component configuration with sandcastle.config:


Merging custom build component configurations
    Could not find configuration 'Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2' (instance 1) to add configuration for 'Custom Website Reference Links' so it will be omitted.
    Last step completed in 00:00:00.0930

When I open up sandcastle.config in the Working directory, I do see build components with type="Microsoft.Ddue.Tools.ResolveReferenceLinksComponent2". The fact that SHFB is unable to merge is weird to me since I pretty much based the build component configuration off the standard "Cached MSDN URL References" component config found in SandcastleBuilder.components file, the only difference being insert="before" instead of insert="replace" and some additional default configuration which is not applicable in my case. When I disable my component or remove my component and add "Cached MSDN URL References", it gets merged fine and runs. It is only my custom component configuration that is not successfully merged,

I tried:

  1. Using insert="replace" instead of insert="before" just to see if it makes any difference. The result is the same.
  2. Instead of adding component configuration file into the special folder, I tried adding the configuration directly inside SandcastleBuilder.components. The component configuration gets picked up by SHFB, but still cannot be merged, the error message being the same.
  3. Using insert="start" instead of insert="before". With this configuration, the build component does get added to sandcastle.config, is successfully instantiated and applied (even though it does nothing at this point). But I believe inserting it at the start is not an option for me and I really do need to insert it just before ResolveReferenceLinksComponent2.

Could you please help me on this? I am not at all sure where I am going wrong.

Thanks in advance,


Mar 27, 2012 at 11:34 PM

I forgot that this is within the multi-format component so there's one section for each help file format.  Also, I'd suggest using "after" placement and the component before the resolve reference link component so that it won't fail if using the cached build components too.  The example below should get it working:

<?xml version="1.0" encoding="utf-8"?>
  <component id="Custom Website Reference Links"
      <description>This build component can use custom links.</description>

      <configureMethod name="-" />

      <insert placement="after" type="Microsoft.Ddue.Tools.SharedContentComponent" />
      <insertConceptual placement="after" type="SandcastleBuilder.Components.ResolveConceptualLinksComponent" />

      <!-- This component is output format dependent so a configuration for each output format is provided. -->
        <helpOutput format="HtmlHelp1">
          <!-- Add default config options here if any -->

        <helpOutput format="MSHelp2">
          <!-- Add default config options here if any -->

        <helpOutput format="MSHelpViewer">
          <!-- Add default config options here if any -->

        <helpOutput format="Website">
          <!-- Add default config options here if any -->





Mar 28, 2012 at 7:18 PM

Thank you Eric, that did the trick.

Mar 30, 2012 at 2:03 PM

I have one more related question though. Can SHFB search for *.components files somewhere relative to the build project? Or is it fixed to the special folders?

My goal is to have the build project self-contained including the necessary non-standard build components. I put the help project under source control along with my custom build components. The current state is that everyone checking out the help project and trying to build it must also have the build component "installed" in the special folder.

Mar 30, 2012 at 4:09 PM

Build components and plug-ins have to be in one of the special well-known locations as once loaded, they are not searched for again.  The search happens on first use.  See the Special Folder Locations topic in the help file for more information.  Basically, it will search a folder pointed to by the SHFBCOMPONENTROOT environment variable (optional, does not exist by default), then the folder pointed to by the SHFBROOT environment variable, and then the common application data folder.  Typically, build components and plug-ins are generic and are for use by any project and will not change that often if at all once developed.  As such, they are not considered project-specific items.  It's possible you could deploy your components to a common, shared location and point the SHFBCOMPONENTROOT environment variable at that location for SHFB to search.