Diagnosing Code Download Problems
By Conrad Herrmann
25 July 1997
So you’ve just build a nifty new ActiveX control or ActiveForm, and you’re eager to test it out in the field. You type in the information into the Delphi’s Web Deployment options dialog and select the Web Deploy command. Then you go to your coworker’s machine—one on which neither your control nor Delphi have ever been installed—and you go to the test web page Borland’s deployment Wizard generates. After a second or two, your heart jumps as you see the magic words appear:
Delphi ActiveX Test Page
You should see your control appear below this line:
A bit more crunching, and the screen looks like this:
You’ve just been given the Big Red X—an indication that the Internet Explorer was unable to download or create your control. What happened, and how can you fix it?
Any number of errors could have occurred, but Internet Explorer suppresses all the error messages making it frustratingly difficult to diagnose failures. This is a usability feature.
The idea is that the Internet Explorer shouldn’t pop up error messages that the user isn’t capable of dealing with anyway, and most end-users can’t tell the difference between an Authenticode security violation and the Start button. So, your control’s users will be happy and ignorant—who cares if you get a bald patch prematurely?
This paper presents an overview of the code download process Internet Explorer uses to retrieve and install your control, and presents a diagnostic schema for analyzing what’s wrong in your installation.
The Download Process
In order to create your control in the web browser, Internet Explorer must hav received an HTML file containing an <OBJECT> tag. This tag contains parameters that dictate the first steps in the download process.
<OBJECT classid="clsid:29D37F03-F02F-11D0-ACB2-0080C7316F20" codebase="http://www.xyz.com/MyControl.ocx#version=1,0,1,0" width=350 height=250 align=center hspace=0 vspace=0 </OBJECT
The #version part of the tag is optional—if missing, it means "any version will do." The version tag must not appear if the client is the Netscape Navigator with the NCompass ActiveX plugin.
On the web server, there will be a file called MyControl.htm (many servers are case sensitive) , which has been stamped with a version tag (presumably 220.127.116.11), and which can create an ActiveX control with the specified ClassID. The first thing Internet Explorer does is to determine if the specified ClassID is already installed on the client machine. If it is, IE will check to see if the installed version matches the requested version. If the local version matches the version requested in the HTML, IE will simply use the local copy to create the control.
If the version number requested by the HTML page is newer than the one currently installed, or the ClassID is not yet installed, IE knows it must download and install the codebase before it can create the control.
Download and Install Steps
Downloading and Installing the codebase involves three basic steps:
- Copy the code base onto the local machine’s Windows/OCCache directory or a subdirectory of it.
- Check the code signature of the codebase, and
- Install the codebase.
If this process completes successfully, the machine should have a correctly registered OCX library from which the control can be created.
Copying the codebase
The first step, copying the control to the local machine, will be done by attempting to retrieve the file by the mechanism that the codebase URI specifies. If the URI says use HTTP(the default), then IE will use HTTP to download the control. You can also specify FTP, or FILE URIs.
This step can fail in a nuber of ways—if the remote server can’t be found, if the local disk is out of disk space, if the codebase name is spelled incorrectly (remember, many servers are case-sensitive), etc.
You can simulate this step by typing the URI into the IE address box. IE should respond with a dialog that says "Do you want to Open It or Save It?"—if you choose Save It and type /windows/occache as the directory, then this should yield exactly the same results. In the case of a connection failure or File not Found error, you will know that the URI path points to a server or a file that can’t be found. If this happenes, you may have forgotten to deploy your file to the server, or you may have typed the codebase’s URI incorrectly.
This step is the only step that gives you visual feedback, and it only does so if you’ve got a quick eye or a slow modem. When IE is downloading the codebase, you’ll see the IE’s download-progress meter (in the status bar) moving from left to right. If the status meter stays at 0%, then there is probably a connection problem. If the progress meter moves all the way across to the right, then the codebase probably was correctly copied to your machine, and the problem lies at a later stage.
One problem that often happens if you’re debugging and testing on your development machine is that you’ve left the control open in the IE browser. While your control is running, the DLL file itself is locked, so the code download process will not be able to overwrite this file. Remember that IE caches the last few pages you looked at, so even if the current page isn’t the one with your ActiveX on it, you might still have the OCX locked. Exiting IE is the only sure way to know that IE releases the lock on the DLL file.
Checking Authenticode Signature
In the second step, IE checks the code signature of your control. The kinds of errors that can occur depend on the security settings in your IE installation. If you have security set to High, IE will refuse to install the control if it hasn’t been code-signed, and will fail silently. If security is set to Medium, IE will show a warning dialog that reads "This component has not been digitally signed by its publisher. Do you wish to continue?" When security is set to low, IE will not check for a code signature at all, and will proceed to the Installation phase.
When security is set to Medium or High, and IE validates the code signature on your codebase, it will display the telltale certificate dialog which indicates it was able to verify the certificate. This dialog allows you to summarily accept all code from the specified vendor, and if the vendor already appears on this list then the certificate dialog won’t be shown.
If you’re working with unsigned controls, setting security to Medium rather than low can give you a useful piece of information about what’s happening, if you’re working with an unsigned control. If the "This component has not been digitally signed by its publisher" does not appear, the control’s codebase was not downloaded successfully—either because IE failed to download it, or because IE decided it didn’t need to be downloaded.
There also can be problems with code signature verification if you have not upgraded to Authenticode 2.0. You should make sure to upgrade your development machine to Authenticode 2.0 at the Microsoft web site.
Success? Failure? Which is it?
Telling whether the second step (Authenticode) succeeded or not can sometimes be difficult because there are situations where both success and failure proceed silently. The two cases where success announces itself are:
- Medium security setting, unsigned control, yields the "unsigned control" dialog box.
- Medium or high security setting, no summary accept from your vendor, yields the certificate dialog.
Installing the codebase
The third step is installing the codebase that was just downloaded to your machine’s WINDOWS/OCCACHE directory. How the codebase is installed depends on which kind of codebase you have. The type of codebase is determined by the CODEBASE tag in the OBJECT command. If the file is a DLL file (usually with extension .OCX), then it is the entire codebase. If the file is a .CAB file, then the codebase contains multiple files that are contained in the CAB file. If the file is a .INF file, then the .INF file describes a list of other files that make up the codebase, and where these can be found.
If the codebase is simply a DLL/OCX file, the installation only requires loading the DLL and then calling the DllRegisterServer function in the DLL. If this function succeeds, IE can then try to create the control.
There are two common points of failure in this scenario, both of which fail silently. The first is if the DLL can’t be loaded on the client machine using LoadLibrary. This usually happens if the DLL is dependent on other files, such as library DLLs, Delphi packages, or even specific system DLLs that aren’t available on the client machine. Load failure can also occur if the DLL file was corrupted. If the DLL fails to load properly, no code in the DLL will execute, which means the DLL cannot be debugged in the debugger.
Failure can also occur if the DLL can be loaded but it fails to initialize. This usually isn’t a configuration problem, but probably happens because one of your units’ initialization sections throws an exception. You can determine if your DLL gets loaded correctly by setting a breakpoint at one of your units’ initialization section. If the DLL gets loaded, the initialization sections will be executed, and you can step through their execution until you find the failure.
Another failure can occur if your control cannot register itself correctly. This can happen if your control doesn’t export DllRegisterServer, or if this function fails. Since most Delphi ActiveX controls start with code generated by the Wizard, the first of these is unlikely. There are number of reasons why registering the DLL server might fail, but a common one on NT is caused by inadequate user rights. Each object is registered by its factory (the object you created in the initialization section of your control’s implementation unit), so if any of the factories fail to register the entire server will fail to register. If you use custom factory classes, you might want to check that these classes don’t fail on the user’s machine.
Creating the control
Once your control is correctly installed and registered, IE tries to create an instance of the control. If you’e tested your control locally on your development machine, it’s unlikely that this step will fail, but there are a few errors that will make you just say DOH!
The first is that the ClassID in your HTML file may be incorrect. Up until this point, the ClassID specified in the HTML has played no part in the code download process, so an incorrect ClassID would only show a failure in this phase.
Various low-memory or low-resource conditions might cause your control to fail to create itself as well. The object creation will fail if your COM object fails to construct itself. If you’re building an ActiveX control, your control’s Create or Initialize method might throw an exception or otherwise indicate failure (this is a condition you can debug).
Putting the control in the HTML page
After the control is created, there are still conditions that might fail the installation of your control into the browser’s HTML page. If your <OBJECT> tag contains PARAM statements for your object, the control must be marked safe for initializing in order for IE to allow it to appear on the page, if your security setting is Medium or High. If the HTML tag declares your object available for scripting on the page, IE checks that the control is safe for scripting. In either case, if the control is appropriately marked, and security is Medium or High, the control won’t appear.
Note that the Delphi ActiveX Class Hierarchy doesn’t support the PARAM tag by default—this is a feature you must implement on your control yourself. Nevertheless, it’s not uncommon for a beginner who doesn’t know this to supply a PARAM tag on the HTML page. Because the control is also not marked safe for initializing by default, supplying the PARAM tag will suppress your object’s installation on the HTML page even if the object doesn’t have the means to receive these PARAMs through IPersistPropertyBag.
If you have a script that refers to your control, and the control wasn’t marked safe for scripting, the script will probably give you a runtime error when it tries to access the (now nonexistent) control on the page.
The trick to diagnosing the failure of any complex process is to recognize the signs of success or failure of each step in the process. While IE intentionally suppresses most of these clues, it leaves you with just enough information to be able to diagnose what it’s doing.
The attached flowchart summarizes the code download process, and can help you to diagnose a failure in your download.
Code Download Flowchart
Use this flow chart for diagnosing download errors.