Something I've been curious about for a while now is how to extend the SharePoint help system. A while back I wrote about how to modify 'system' pages in SharePoint by effectively adding new pages - the examples I used were:
- a custom Recycle Bin page which displays only items deleted by the current user
- a custom Central Admin page which has a message specific to my fictional organization's administrators
When implementing customizations like this, I thought it would be useful to be able to add custom help to accompany the new functionality. So today I set about digging around the SharePoint help system to see how to do this. Unfortunately my answer so far is that it's pretty difficult and I haven't figured out all the pieces! However, I thought I'd detail what I found in the hope that either it's still useful to somebody, or that someone who knows can perhaps leave a comment or link and complete the jigsaw.
So to be clear, I'm talking about how to add custom application help pages here - nothing to do with the 2 .chm files which are the WSS and MOSS SDK references. In site or central admin pages, the application help pages are linked to from help icon on the top bar:
As you'd expect, this icon (and the link behind it) is provided by the master page for the page. Clicking the link calls a JavaScript function called TopHelpButtonClick() in core.js to open the help window - on most pages a parameter of 'NavBarHelpHome' is passed, though notably pages which link to a page other than the default help page override this value. Since all pages in say, Central Admin share the same master page (and the JS call is in the master page, not the actual page) the code in core.js checks to see if the page itself has specified an override. Individual pages can therefore override the help location specified in the master page using a script block such as:
<script type="text/javascript" language="JavaScript">
var navBarHelpOverrideKey = "OSSCentralAdmin";
</script>
Core.js will then build a link with this override parameter in rather than 'NavBarHelpHome', meaning that pages can easily link to a custom page rather than the default. In order to link to a custom help page, your page will need to override this value.
The value used here links to a value in a set of mapping files stored in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML\HELP. In the case of the value shown above, we find that one of the mapping files, 'OssSearchAdmin_HelpKeymap.xml', contains the following:
<helpmap>
<key>OSSCentralAdmin</key>
<collectionId>MS.SEARCH.ADMIN.manifest</collectionId>
<contextId>MS.SEARCH.ADMIN.OSSCentralAdmin</contextId>
</helpmap>
The set of mapping files in this directory all contain similar entries, i.e. a corresponding entry for each page which specifies an override to the default help page. Since these files don't appear to follow any naming convention, I'd venture that any XML file with the correct schema can be dropped in here and the help system will pick it up. When it comes to finding what these references point to, things get interesting! An initial search across the '12' directory using Visual Studio 'find in files' yields no results, but as with most of these things it's worth digging further. In the '\12\HCCab\1033\' directory are a set of .cab files which store the help files used in the SharePoint help system. In the example above, the 'MS.Search.Admin.HC.cab' file is the file which is referenced. Looking inside, we see a number of files, one of which is named 'MS.SEARCH.ADMIN.manifest.xml', which you'll notice is the value for the <collectionId> in the mapping above. The contents of one such .cab file look like:
So a quick recap of so far - we've found how to override the initial help page which is displayed, and how the key specified links to a set of help files packaged as a cab file in the 'HCCab\<localeId>' directory.
The manifest file is obviously key to how the index of the files in the .cab are linked. Incidentally, for those familiar with building SharePoint solution packages, the schema used here is completely unrelated to the 'manifest.xml' file used there. Looking at the contents of one of these manifest files, the first thing that strikes me is it looks like a system-generated file - for one thing there are many parent/child and link relationships which would be complex to document by hand. An extract looks like:
<?xml version="1.0"?>
<helpCollection>
<name>SearchCentralAdmin</name>
<id>MS.SEARCH.ADMIN.manifest</id>
<changedDate>2006-10-13 21:53:57Z</changedDate>
<createdDate>2006-10-13 21:53:57Z</createdDate>
<author>Microsoft</author>
<version>11.0.9413.2</version>
<lcid>1033</lcid>
<defaultHelpItem>MS.SEARCH.ADMIN.HA10175815</defaultHelpItem>
<brandingImage />
<rootCategory>MS.SEARCH.ADMIN.CH10176169</rootCategory>
<feedback show="False" />
<helpItems>
<helpItem>
<id>MS.SEARCH.ADMIN.HA10047848</id>
<parents>
<parent sortOrder="4" primary="true">MS.SEARCH.ADMIN.CH10176336</parent>
<parent sortOrder="4" primary="true">MS.SEARCH.ADMIN.CH10176336</parent>
</parents>
<relatedItemsPointingToMe>
<item sortOrder="1">MS.SEARCH.ADMIN.HA10047848</item>
<item sortOrder="1">MS.SEARCH.ADMIN.ManageSearchService</item>
<item sortOrder="1">MS.SEARCH.ADMIN.SearchServerSettings</item>
</relatedItemsPointingToMe>
</helpItem>
<helpItem>
<id>MS.SEARCH.ADMIN.HA10047852</id>
<parents>
<parent sortOrder="6" primary="true">MS.SEARCH.ADMIN.CH10176338</parent>
</parents>
<relatedItemsPointingToMe>
<item sortOrder="1">MS.SEARCH.ADMIN.LogSummary</item>
<item sortOrder="1">MS.SEARCH.ADMIN.LogViewer</item>
</relatedItemsPointingToMe>
</helpItem>
However, one thing which does check out is that the file referenced in the <defaultHelpItem> is indeed the page which is loaded initially when the help window opens. So that's something!
I can't help thinking though, that a help file generator has been used and it would probably be necessary to use the same approach to add custom help pages. When I started delving I mainly expected to find some .chm files generated by nDoc or Sandcastle somewhere, but it does seem like something I'm not familar with has been used. Robohelp perhaps?
If anybody can shed any light on this I'd be interested to hear. In the meantime, I note that others have found alternative ways around the problem, by passing a custom parameter and then modifying core.js to intercept this and open up a completely custom help window, rather than plugging into the existing help system as such. Ragav Jagannathan's post on his approach can be found here - http://ragavj.blogspot.com/2007/04/custom-help-window-can-be-opened-by.html. As Ragav rightly points out, customizing the core.js file is unsupported so you should probably think carefully before going down this route.
[Update - Nick Swan MSN'd me to point out that there is a document library in the Central Admin website which contains help files. Interestingly, it's the same set of files stored in the HCCab folder on the filesystem! It's difficult to tell from the IIS logs which set of files are actually pulled in, as they seem to be dynamically loaded through the '/_layouts/helpContent.aspx' and '/_layouts/help.aspx' pages. Interesting!]