One of the greatest parts of modern development for me is the combination of Intellisense and F1 help for an API. For a really great API you can usually figure things out from naming and the very short bits of help in Intellisense what to do and why. But, anything that requires more than one call to complete benefits from deeper help. It’s great to be able to, right in the moment you’re puzzling “huh, why this and not that?” press F1 and *poof* there’s a page of help about right where you are with links to go deeper, higher, or over to where you need to be.
This is why it was a top priority for us to get Visual Studio integrated help ready even while we were still in Beta. Since we’re also big fans of Continuous Integration, it wasn’t long after we got our build server set up we were configuring automatic API help generation as well. Initially we started with Sandcastle, but in the end we get better results from a commercial product, Document! X. It was also a lot easier to set up and use, which in our case alone was worth spending some money to save a lot of time.
So the final step to good help was integrating the HTML Help 2 output into the installation so that the Windows Installer produced by our build process would install the Visual Studio integrated help. Here’s where we’ve come to a screeching halt. The problems start with what it takes to register HTML Help during an installation. There are basically two approaches:
- Use a registration program, such as H2Reg. This is also known as the Bad way. In the end, you’re relying on an executable fired up on the target system at a key point in the installation to make it work. If this is on Vista it may not run with Admin access. You may run into problems with auto-deployment in enterprises where they’re expecting everything to be done by Windows Installer itself. In the end, you really are better off not going this way if you can.
- Create a custom mangled Merge Module for your help. This is the official Good way. The problem is that it isn’t enough to just put your help files, or even any set of files, directly into the merge module. Microsoft has published two approaches, and both are flavors of “re-edit the final merge file after the fact to make it all work”.
For the highest compatibility and best customer experience, it was very important to us to have a single MSI file that could work in an enterprise scenario. To this end, Microsoft published the directions on how to create a correct merge module for help, including how it has to be manually modified after generation to fix it. These directions are complicated and a challenge to get done correctly. Fortunately, Microsoft created and shipped a few years ago the Help Integration Wizard to solve all that.
Running through the wizard, the biggest problem was knowing what magic values needed to be set, and what values shouldn’t be changed to make it all work. The documentation really isn’t of much help here; while Microsoft dramatically improved it for 2008 that appears mostly to be about adding screen shots of each page of the wizard, not giving any guidance about what to put in it.
There’s Always a Catch
All appeared rosy: You run through the wizard and with some cross referencing come up with what appears to be the right magic values, and you’re set. What comes out the other end is an installation that actually seems to do what it should: There’s your help right in MSDN with the rest of it, F1 ready to go.
My first clue that all was not well was when I noticed that the merge module created by the Installation wizard isn’t set up to check everything it needs into source code control. Indeed, if you check it into source code control very little is put in – none of the critical files that it actually generates during the wizard process. Not good. Also, it uses paths to things that aren’t transferable between 64 bit and 32 bit versions of windows (Best guess: The wizard is written in .NET and runs as a 64 bit process, the rest of Visual Studio doesn’t so you get the “real” 64 bit paths to files in the 32-bit area of Program Files.).
Some mild work with manually putting things into source code control later, it now builds repeatedly. And everything works.
Right up until you change the help file. The next build when the help file changes, the resulting install runs… and does nothing. Nada. Quiet as a church mouse. No indication of failure, just… no help.
After some experimentation I determined that it appears you have to re-run the wizard every time you change your help file. Now, nowhere in the documentation could I find any indication on when you have to re-run the wizard: Every time you change anything in the help file? When you change things in the Table of Contents (and think about it – you write content that doesn’t show up in the TOC?)? Adding to this treat is that the wizard can’t be re-run automatically (e.g. scripted) and it creates a new module every time it runs, requiring I modify my installation to include that module instead of the original module. Now see why it doesn’t bother putting the files into source code control? They’re output files.
Seriously? This is the best we can do?
Since the Help Integration wizard has to be re-run each time the help file changes, and it has to be run by a person it can’t be in our automatic build process. That means there’s not much point in having the help build in our automatic build process. In the end, I strongly suspect we’re going to have to go back and figure out how the hard way works and write our own utility to munge the merge module so that we can automate this into the build process.
The irony is that what’s taken the most time for us in this affair is the lack of documentation on how the help integration wizard works: When it has to be re-run, what exactly it expects you to put into your resulting installation (there are some mysterious merge module dependencies and oh yeah, you get some warnings when you build your installation. The documentation in one area says they can be safely ignored if your install works. Nice bar.)
It’s all solvable: This can be made to work, and it’s not the worst problem we’ve ever faced. But in the good old days of COM you just had the help file in the same directory as the binary and that’s it, you’re good to go. Now we’ve improved things and it takes a hand-crafted binary file and adds minutes to the install time for users. The point is that it really didn’t need to be this way – A major advantage of having tight control over the platform (and it’s hard to argue Microsoft doesn’t have that between Visual Studio and .NET) is making everything easy.
Apple would have done it.