Windows help devolution

I have been writing Windows help files for nearly 30 years. It’s a very time consuming process to set up and maintain application help files. And just when I think I have a stable, workable system, Microsoft pulls the rug out from underneath me.

With the introduction of Windows Vista in 2006, Microsoft deprecated WinHelp and no longer includes it with the factory images of Windows Vista, Windows 7 and Windows 8.

HTML_help is Microsoft’s replacement for WinHelp. However, the Windows HTML_help viewer is crippled. It will only open CHM help files on a PC, not those stored on an intranet. Instead of content, the viewer displays the absolutely meaningless “Navigation canceled” message:
HTML_help

I have never understood this. An intranet is an internal network, so why in the world would it be considered a security risk to open a file on your own internal network? Apparently, Internet Explorer (tightly integrated into the Windows OS), is not able to discern the difference between the internet and an intranet.

So, I have been sticking with WinHelp as it is freely available for download from Microsoft for Vista, Windows 7 and (surprisingly) Windows 8, with both 32- and 64- bit versions:

Not until my PC at work was (finally) updated to Windows 7, did I realize that WinHelp is now just as useless as HTML_help. Windows 7 now blocks WinHelp from opening HLP help files stored on an intranet.

Again, WTF? What is the security risk of opening a file on your own internal intranet?

I could not find a trustworthy third party HLP file viewer, so I decided to switch to the CHM help format and seek out a replacement for Microsoft’s HTML_help viewer for intranet applications. After hours of web searching, I eventually found xCHM, a free, open-source, multi-platform, functional replacement for Microsoft’s HTML_help viewer.

Although it doesn’t have all the bells and whistles, xCHM does, at least, open CHM help files stored on an intranet.

In order to utilize xCHM, the help calls in APK had to be rewritten. Logically there are three scenarios:

  1. If the program is running from a local drive, the default help handling system is called.
  2. If the program is running on an intranet, and xCHM is available, then xCHM is called to display the relevant help topic.
  3. If on an intranet, and xCHM is not found, then an error dialog is displayed with a link to web help on rxkinetics.com.

Code snippets

Determine if the program is running locally or via intranet:
function TfrmMain.IsOnLocalDrive(): Boolean;
var
aDrive: string;
begin
aDrive := ExtractFileDrive(Application.ExeName);
if (GetDriveType(PChar(aDrive)) = DRIVE_REMOVABLE) or
(GetDriveType(PChar(aDrive)) = DRIVE_FIXED) then
Result := True
else
Result := False;
end;

Determine which help system is available:
function TfrmMain.LocalHelpAvailable(): integer;
begin
if IsOnLocalDrive then
result := 1
else
begin
if XchmInstalled then
result := 2
else
result := 0;
end;
end;

Intercept the application help call and choose which help system to use:
function TfrmMain.ApplicationEvents1Help(Command: Word; Data: Integer;
var CallHelp: Boolean): Boolean;
var
MyHelpKeyWord : string;
begin
case LocalHelpAvailable of
0: begin
// On network and xchm is *not* installed
CallHelp := False;
frmHelp_Link.ShowModal;
end;
1: CallHelp := True; // Local drive
2: begin
// On network and xchm *is* installed
CallHelp := False;
// Get HelpContext of current active control
MyHelpKeyWord := IntToStr(Screen.ActiveControl.HelpContext);
// If control HelpContext is blank -> Get Parent HelpContext
if MyHelpKeyWord='' then
begin
MyHelpKeyWord := IntToStr(Screen.ActiveControl.Parent.HelpContext);
// If parent is blank and parent is not a form, get form HelpContext
if MyHelpKeyWord='' then
begin
if Screen.ActiveControl.Parent <> Screen.ActiveControl.Owner then
MyHelpKeyWord := IntToStr(Screen.ActiveForm.HelpContext);
// Fallback: if control, parent, and form HelpContext are all blank -> display start up topic
if MyHelpKeyWord='' then
MyHelpKeyWord := '10';
end;
end;
ShellToXchm(MyHelpKeyWord);
end;
end;
end;

Shell out to xCHM:
procedure TfrmMain.ShellToXchm(HelpTopic:string);
var
strParameters : string;
begin
// Create parameter string -- Requires short path name!
strParameters := ' /c ' + HelpTopic + ' ' + GetShortName(PathName) + 'apk.chm';
// Shell out to xCHM
ShellExecute(Application.Handle, 'open', 'xchm.exe', PChar(strParameters), PChar(PathName), SW_SHOW);
end;

Looking back, this has probably been an exercise in futility. It seems as though most pharmacists either don’t know there is a help system built into the program, or they don’t care. Either way, no one has bothered to contact me to report a problem. Why am I not at all surprised?

Comments are closed.