Databases - Testing ISAPI DLL's with IIS

Regardless of the language, it is a challenge to test ISAPI DLL's with IIS. The main issue is that once IIS loads a DLL, it never releases it. Therefore, the only way to test your changes is to restart IIS so that it will use the new version of your code.

The reason to use ISAPI DLL's is that they are much faster that CGI (*.exe) files. This is particularly true when accessing a database (which is the main reason for writing a web server in the first place).

| | | |


There are 4 basic ways to shutdown and restart IIS


Some (definitely not all) versions of IIS are distributed with a command that can be used to restart it. With IIS version 5, the command is iisreset.exe.

There are also commands to shut down groups of dll's. (Apparently, this capability was added with IIS 4.)

About Applications

IIS allows you to manage the server as a "group of applications". The server root is always an application. You can add as many as you like. In general, IIS runs as a process and all the applications run in the "pooled" process. For test purposes (as well as for other reasons), you can run an application in its own (isolated) process - for performance reasons, there should be a maximum of 10 isolated applications (processes).

From a test point of view, the main benefit of running your site in an isolated process is that you can shut it down without affecting the other sites running under IIS. This means that to replace an active dll, it is not necessary to restart IIS, instead you just restart the process.


Defining an Isolated Process

In the IIS Manager, right click the virtual directory and select Properties. On the Virtual Directory tab, there is a field called Application name, if it is grayed out, then click the Create button. Set the Application name to whatever you like. Set Application Protection to High (Isolated). (Be sure that Execute Permissions is set to Scripts and Executables.) Click Apply

The icon will change to an open box.

(This can also be accomplished via the command line.)

Once any dll in this application is loaded, the Unload button will allow you to stop the execution of all the related dll's so that you can write new versions over the old. (To enable the Unload button, you must reopen the Properties dialog box.)

Reference: IIS 5.1 Documentation - About Applications


Stopping an Isolated Application

From the command prompt enter The "/w3svc/1/root/" prefix is based on the examples (where that is all that is entered) - I saw nothing in the help files indicating that your application name needs this prefix.

If the path on the vbs file is omitted, then it defaults to

It appears that there are 2 VisualBasic Script interpreters

BTW, cscript is here


With Windows XP, dllhost.exe can be killed by pressing Alt-Ctrl-Del and killing both instances of that file.


Microsoft suggests using iisreset (new for IIS version 5) from the command line. This could take one minute for IIS to stop.

Kill (or taskkill or pskill) is much faster than iisreset, but there is the problem of knowing exactly what to kill. For instance killing dllhost.exe produces errors that require you to manually restart IIS after every 6 compiles.




IIS 5 comes with a number of administration scripts (written in vbs). These use OLE to access IIS and do various functions - including IIS shutdown and unload a dll (actually, a group of dll's). The scripts are located at

In a nutshell, this unloads all dlls in a directory

IIsObject = GetObject("IIS://localhost/path")
IIsObject.AppUnload
Reference on ADSI - http:www.agnisoft.com/adsi/Conf2000/3132.htm provides Delphi examples
VAR ogj : IADs;
hr := ADsGetObject('IIS://localhost/xyz', IID_IADsContainer, obj);
obj.
IIS Administration Script Utility (adsutil)


Archive - Working all this out was not easy, these are some of the other paths I pursued before finding a winner.

Remember, I started with PWS and older versions of IIS that do not support iisreset.


Testing

This is the problem with dll's - they are very difficult to test.

Basically, the web server (IIS in my case) opens the *.dll file and never closes it. Microsoft does not provide any mechanism for a dll to close itself - it must be closed by the program that opened it. Microsoft also does not provide a way for IIS to close individual *.dll's. As a result, you must shut down and restart IIS before your changes will take effect. (This is why I originally suggested developing your application as a CGI file and testing this first before you use it as a dll.)

The other problem is that the Delphi IDE debugger can not be used unless Delphi runs the code. Thus, when IIS runs your code, you will need to use other methods to debug it.


3rd party tools

Dataweb provides Free ISAPI Tools that

I do not use the first one to unload dll's because it is a little complicated - it requires a password, and it must be run manually.


IIS no-cache option

IIS does have a switch to keep it from caching any dll's - but that kind of misses the point. I want the *.dll to remain in memory for testing and to be automatically reloaded when a new version is available.

Additionally, the switch applies to the entire site, not just the selected directory.

In XP, the switch is available via,

This checkbox is grayed out on the sub-directories.


Test Solution

Based on information in the next section, I developed a Delphi program that automagicly solves the problem when IIS is running on Windows XP.


How to Restart IIS

These are several methods to restart IIS - they are NOT all reliable.


Via the Control Panel

Under Windows 2000, Note: The specifics are operating system dependent.


Killling dllhost.exe via the Task Manager

These instructions are for Windows XP, but the procedure is basically the same for other operating systems.


Using an *.bat file

I wrote the following *.bat file to semi-automate the process under Windows XP. You can run it from a shortcut or from a command prompt in a console window. When executed from a command prompt, these are the expected results
Note: Each operating system uses a different command for this. Windows XP uses taskkill.exe, Windows NT uses kill.exe exeName, I have not found a similar command for Windows 98.

kill.exe is part of the Windows NT Resource Kit.


Using a CGI file

I spent a fair amount of time trying to implement via a CGI (*.exe) file so that I could restart the dll remotely - I never got it to work via a browser. Of course, it works perfectly when you just double click the *.exe file.


How to automatically update dll's

Running Replace_dll.exe on a Windows XP based web server will automatically shutdown part of IIS each time you compile a new dll. Replace ISAPI dlls.zip contains the *.exe, instructions, and full source code.

How it works - This Delphi program checks a sub-directory every 5 seconds. When a file is found, it shuts down the server and moves the file(s) to the main directory.

With this program, dll's are just as easy to test as CGI files.

This program does not work with Windows 2000 because taskkill.exe is not available.

Update: This program crashes IIS after changing dll's 5 or 6 times - apparently, there is a limit to how many "errors" IIS will log before it just quits.

A new program using IISRestart.exe is under development.


Author: Robert Clemenzi - clemenzi@cpcug.org
URL: http:// cpcug.org / user / clemenzi / technical / Databases / Testing_w_IIS.html