I have got a program written in Delphi 2007 that uses html help. Very often it hangs on exit (even though html help wasn't actually called) and I traced the problem down to this call in the finalization section of Windows.pas
finalization
if HtmlHelpModule <> 0 then FreeLibrary(HtmlHelpModule);
end.
The main thread hangs in this call because of a NTWaitFormMultipleObjects deep inside the unload code of the hhctrl.ocx. There are other threads (none of which my code creates) that apparently wait for the same, so my program hangs. I guess some of these threads are created by ADO and/or the Microsoft SQL Server client libraries.
I found one workaround: An additioal call to LoadLibrary('hhctrl.ocx'), so the call to FreeLibrary in Windows.pas does not actually unload the dll but only decrements the reference count to 1. While this seems to work, it does not not feel right.
Is this a known problem? Is there a proper solution?
(Yes, I googled, but found nothing that helped. This seems to describe a similar problem https://social.msdn.microsoft.com/Forums/en-US/7bce34a2-50a0-411d-872f-0626360d5415/dll-sometimes-hangs-on-unload?forum=vcgeneral with a different DLL.)
EDIT: Some more info:
The problem apparently only occurs when the html help is never called within the program (so LoadLibrary('hhctl.ocx') wasn't called). On shutdown, the finalization code in htmlhelp.pas tries to close all htmlhelp viewer windows (of which there are none) and issues the first call ever to the HtmlHelp function. This leads to a call to LoadLibrary in windows.pas. If I show any htmlhelp in the program, everything works fine. So, I think this might be a problem with calling LoadLibrary('hhctl.ocx') within the finalization of the RTL. But I have no idea how I can avoid this.
Normally when a host application closes, Windows closes all Help windows opened by this application automatically. There is a problem ... This can cause access violations.
I'm not a Delphi programmer - more busy in help authoring (CHM's) and VB. You can try using the HH_INITIALIZE, HH_UNINITIALIZE commands. These are documented in the HH Workshop online help. But - please check your code for HH_CLOSE or HH_CLOSE_ALL too.
Call HH_CLOSE_ALL earlier. Get more space between the HH_CLOSE_ALL and your call to UnloadLibrary. In VB and Delphi you would perform the call on the Form QueryUnload not on the Form Close or Destroy.
A work around is to close the HH windows by hand or earlier in the CloseQuery() Event and use sleep(0) to give a few cycles for HTMLHelp to settle down.
or
sample:
Don't blindly call HH_CLOSE_ALL on shutdown. If a user does not have HTML Help installed then this call will crash your application. Here is safer code. Notice we are checking if HH is installed before calling HtmlHelp();