Tutorial: Debugging the SHFB Build Process

Topics: Developer Forum
May 1, 2014 at 3:57 PM
Edited May 1, 2014 at 5:21 PM
Hi everyone,

This is something I wanted to share which saved me a lot of time
hoping it's not already have been fully covered being "How to Debug the SHFB Build Process"
in order to pin-point the problems with your doc sources, config, components, plug-ins etc...

This might look elementary to some, if so, you're welcome to comment.

OK, we already know that sand castle projects are Visual Studio projects
thus the build process is covered by the Microsoft MSBuild.exe executable.

This is the root of the build process thus what we're willing to debug.
If you're like me you didn't know you can debug a random .exe assembly
in Visual Studio.

What you do is that you create an empty VS project/solution. Then add an existing
project specifying MSBuild.exe path (Defined later).

From here we an specify arguments similar to the recommendation for running
the build process in post-build event in documentation. E.g.:

Exeutable: C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe

The PARAMETERNAME=ARGUMENT pair is actual command-line variables that will be set
that you'll be able to handle in you SHFB project pre-build event.

By the mean of fancy SHFB configuration files, MSBuild.exe launches multiple other processes.
This includes itself (MSBuild.exe) and SHFB internal executables, e.g.: BuildAssembler.exe.
(I don't know if it's the case but I think the reason there's so many internal executables
in SHFB is because there would be no way of using DLLs inside the MSBuild project files.)

Child processes issued from MSBuild.exe are not attached to the debugger automatically.
The debugging faces a dead-end. What we can do is to attach the child MSBuild.exe processes
manually but a lot of child processes will spawn by MSBuild.exe at unpredictable moments.

So what I did is I installed a Visual Studio extension called Visual Commander (See Link) and defined a new custom C# command.
Basically it's a simple application with a background worker that auto-attaches spawning processes based on their names.
It has rough edges but it has an advantage over commercial products, it's free and I'm giving it for you now Download the command here. Download VSCMD then the command, then import it.
You'll easily find the string array where you an add your own processes to attach. I do feel that only MSBuild.exe
should be there since its native and only native processes spawn unattached, but I might be wrong and you might want to add
all SHFB executables in there.

Regarding managed assemblies, debugging is not very useful without symbols and especially when assemblies are built
in "Release" optimized mode. So if you want to debug SHFB internals, you need to re-build SHFB its code source in "Debug" mode.
As for symbols, SHFB solutions are already configured to generate them.

First download the SHFB source, then open the "MasterBuild.bat" batch file,
change the line IF '%BuildConfig%'=='' SET BuildConfig=Release to IF '%BuildConfig%'=='' SET BuildConfig=Debug

and execute it. Assuming you currently have SHFB installed. Take the content of the newly built SHFB binaries in PATHTOMYSHFBSOURCEFOLDER\SHFB\Deploy
and copy them to SHFB install folder. In most case: C:\Program Files (x86)\EWSoftware\Sandcastle Help File Builder\
Overwrite the content with the new files.

Last thing to do (optional) is to configure Visual Studio so it can download symbols directly from MS. Click here for a turotial.

Voilà, you`re all set-up. Now use the command each time you want to debug. The debugger will break in SHFB code
automatically on thrown exceptions granted you set your debugger to break on thrown exceptions. Click here for documentation

That's all, I hope that helps and that I'm not re-inventing the wheel.

May 1, 2014 at 7:30 PM
See the ReadMe.txt file in the root folder of the source code. It'll guide you on building a development copy of the tools. If you want debug builds, you don't need to modify MasterBuild.bat, just pass Debug in as a parameter. Also, if you set SHFBROOT to point to the development folder such as C:\CP\TFS01\SHFB\SHFB\Deploy, you don't need to copy the tools to the normal installation folder. Switching between the debug and release builds is done by resetting SHFBROOT.

Each tool also has its own solution file. Some that are a set such as BuildAssembler and the related build components have a common solution. As such, once you set SHFBROOT to the development location you can open that solution to debug just that particular tool. You can set up the debug options so that it runs in the working folder of the failing SHFB project and can use the files from it (just turn off the "Clean intermediate files" project option first). You can also set the debug options to run MSBuild using the intermediate build projects in the working folder rather than the tool directly.

May 1, 2014 at 8:41 PM
Hi Eric,

You're right. There perhaps were no need of modifying MasterBuild.bat directly.
Changing SHFBROOT is a great shortcut from having to copy new binaries to install folder directly.

So basically what you suggests to debug a component, is to open its solution,, change its binary output folder to SHFB install folder,
start the component solution in debug mode and then run SHFB?
turn off the "Clean intermediate files"
No to delete the whole binary output folder I presume.
You can also set the debug options to run MSBuild using the intermediate build projects
How? Ain't any bilt SHFB project points to the install folder somehow.

Having worked with SHFB, created plug-ins, components, syntax generators ...

I think this tutorial or a similar one should be added to SHFB.
I really don't see why this open source project shouldn't have this straight forward way of getting debugged.

This would mean a little less log error dead-end kind of questions and a better reputation for SHFB.

If interested, I invite you to take the content of the turorial as well as the Visual Commander command I've attached.

May 2, 2014 at 2:26 AM
No need to alter where the build output is sent. All of the projects are set to send their output to the .\SHFB\Deploy folder hence the reason for just pointing SHFBROOT there. Once you set the project's debug options, you'd just run the project. For those you want use MSBuild with, you'd set the program to start to MSBuild.exe.

I can add a tutorial for debugging the source but to be honest, it's not something most users will do so it's a low priority.

May 5, 2014 at 2:29 PM
I understand the overkill of debugging all at one might be one's choice.
I rather debug more things and not deal with identifying what module is faulty to load and debug it separately.

You say most user won't do debugging. That's surprising, as I kind of assumed the target audience were programmers.
Don't be mistaken, SHFB is extraordinary, but business requirements often require adjustments that are out of scope
which induce needs of getting one's hands dirty and by extension the use of a debugger.

See you in a next post.
May 9, 2014 at 5:28 PM
Edited May 9, 2014 at 5:30 PM
Additional tips:

Sometimes processes spawning from MSBuild.exe building a SHFB Project execute so fast, the tool I provided can't catch it fast enough.

I found I trick to debug them thoroughly.

First follow this tutorial to activate the hidden /debug switch on the MSBuild.exe executable.
Add MSBuild.exe as an existing VS Project with parameter specifying your SHFB project.
Assuming that you have source code and have re-built SHFB in Debug mode (provides symbols and un-optimized debuggable code)
and replaced the binaries of installed SHFB.
Open BuildProcess.cs in your VS instance containing MSBuild.exe and add breakpoint before a child MSBuild.exe call.
Now find the complete MSBuild.exe command by inspecting variables.
Create a bat file containing the command and add the /Debug switch.

Visual studio will open and you'll be able to finely debug the child MSBuild.exe process.

The idea is to interrupt the BuildProcess and do a MSBuild.exe call in his place.

The profit of the debug switch is that it breaks at the very beginning of the project file
and also you get to debug the .proj file as well as the .cs ones.