Cannot create Conceptual-only documents with Help 2.x

Topics: Bugs, Conceptual Topics, Help 1.x/2.x
Sep 12, 2008 at 7:37 PM
Edited Sep 12, 2008 at 7:40 PM
Hi there.  DocProject is a great tool, so good in fact that I want to use it for ALL post development documentation, including documents that do not have any project or assembly references in them (Conceptual only), like user manuals and training manuals etc.  This I can do for web-based or for Help 1.x but if I switch on Help 2.x I get the following error:

Step 11 of 19: Execute XslTransform

C:\Program Files\Sandcastle\ProductionTools\XslTransform /xsl:"C:\Projects\TFS Demo\Development\Decision Maker\DecisionMaker.UserManual\Help\Settings\Projects\help2x.xslt" "C:\Projects\TFS Demo\Development\Decision Maker\DecisionMaker.UserManual\buildhelp\assembler\reflection.xml" /arg:"basefilename=DecisionMaker User Manual" /arg:"output=DecisionMakerUserManual" /arg:"langid=1033" /out:"C:\Projects\TFS Demo\Development\Decision Maker\DecisionMaker.UserManual\Help\DecisionMaker User Manual.HxC"

XslTransform (v2.4.10520.1)

Copyright ¸ Microsoft 2005-2006

Info: Applying XSL transformation 'C:\Projects\TFS Demo\Development\Decision Maker\DecisionMaker.UserManual\Help\Settings\Projects\help2x.xslt'.

Error: The input file 'C:\Projects\TFS Demo\Development\Decision Maker\DecisionMaker.UserManual\buildhelp\assembler\reflection.xml' could not be loaded. The error is: Could not find file 'C:\Projects\TFS Demo\Development\Decision Maker\DecisionMaker.UserManual\buildhelp\assembler\reflection.xml'.

Non-zero exit code: 1

Step 11 DaveSexton.DocProject.Engine.ExternalProcessException: Execute XslTransform:

The "C:\Program Files\Sandcastle\ProductionTools\XslTransform" process failed with exit code: 1.

The complaint is that it cannot find a reflection.xml file presumably because there are no project references to produce one from. Is this something that can be resolved with an empty reflection.xml file perhaps? or maybe a new "scope" option of "Conceptual only"?

P.S. this is not a disaster as Web based documentation is the preferred option for manuals but I thought you might be interested?

Cheers...   Steve
Sep 13, 2008 at 5:25 AM
Edited Sep 13, 2008 at 6:49 AM
Hi Steve,

Thanks for reporting this issue.  I was able to reproduce it.

DocProject was designed to automatically build standalone conceptual help when there aren't any sources added for reference documentation.  Although a change in the latest version seems to have broken conceptual-only + help 2.x-only builds.

The problem is that I've used the reflection.xml file for the Help 2.x project transformation when I should've used the toc.xml file.  As you've pointed out the reflection.xml file doesn't exist when there are no sources for reference documentation.  Technically, though, any existing XML file will do since the information in the toc.xml file is not used for the transformation at this time.

A quick fix is to add some code to the project's Build Process Component to replace the problematic build step with one that uses the appropriate arguments.  Here's an example in C#.

  1. Add an assembly reference for DaveSexton.DocProject.Sandcastle.dll, commonly found in C:\Program Files\Dave Sexton\DocProject\bin.
  2. Open the project's BuildProcess.cs|vb file.
  3. Add a using statement for DaveSexton.DocProject.Sandcastle.
  4. Append the first block of code shown below to the BuildStarting method.  Make sure to update the brokenStepIndex value to one less than the number of the broken step.  From your example above, you would need to assign 10.
  5. Insert the ExecuteXslTransformFixed and ExecuteProcess methods shown below into the BuildProcess class.
  6. Optionally, if you have multiple DocProjects and DocSites that need this fix, create a new class library project that contains the BuildProcess class with the custom changes that you've made, build it, and register the assembly in the Extensibility | Build Process Component project option in the DocProject Properties window for each project.  Refer to the description window with the option selected for instructions on how to register an external component.  Note that if you sign your assembly and add it to the GAC (gacutil.exe) then you can simply specify the assembly-qualified type name in each DocProject and DocSite that needs it.

Append the following code to the BuildStarting method: 

 // The index of the broken step may change depending upon the chosen project options 
const int brokenStepIndex = 3; IBuildStep brokenStep = context.Steps[brokenStepIndex];

// Insert a dynamic build step to execute a new step in place of the broken step.
// A dynamic build step is required since the BPC is executed in another AppDomain
// but ExternalProcessBuildStep is not serializable.
InsertBuildStep(brokenStepIndex, "XslTransform-Fixed", false, false, true, ExecuteXslTransformFixed); context.Steps.Remove(brokenStep);

Add the following methods to the BuildProcess class: 

private static void ExecuteXslTransformFixed(BuildContext context)
    SandcastleSettings settings = (SandcastleSettings) context.Engine.Settings;

    string docSetFilename = settings.DocumentationSetFileName;

    string projectTOC = System.IO.Path.Combine(settings.TargetDirectory, docSetFilename + ".HxT");
    string help2Project = System.IO.Path.Combine(settings.TargetDirectory, docSetFilename + ".HxC");

    ExecuteProcess(context, settings.XslTransform,
        "\"" + settings.TocFile + "\"",  // this line changes the input XML file to toc.xml 
+ docSetFilename + "\"", @"/arg:""output=" + System.IO.Path.GetFileNameWithoutExtension(settings.CompiledHelp2xFile) + "\"", @"/arg:""langid=" + settings.Lcid + "\"", @"/out:""" + help2Project + "\""); } private static void ExecuteProcess(BuildContext context, string file, params string[] arguments) { using (System.Diagnostics.Process process = new System.Diagnostics.Process()) { process.StartInfo.Arguments = string.Join(" ", arguments); process.StartInfo.FileName = file; process.StartInfo.CreateNoWindow = true; process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; process.StartInfo.WorkingDirectory = context.CurrentDirectory; process.StartInfo.UseShellExecute = false; if (!context.Canceled) { process.Start(); process.WaitForExit(); } } }

Please let me know if that works for you.  In the mean time, I'll add a bug report to the issue tracker so that it will be fixed for DocProject 1.12.0 Production.

- Dave

Sep 13, 2008 at 5:29 AM
Bug report: