次の方法で共有


HOWTO: Replace an ISAPI DLL on a Live Server

Recently, I noticed that I was returning into the bad habit of making just newsgroup replies instead of making detailed blog posts about the question and then posting that URL to the newsgroup. Here's an interesting one about replacing live ISAPI DLLs... but what does making IIS always cache a DLL have anything to do with replacing an ISAPI DLL? Read on...

Question

I'm testing a new and empty IIS 6 site, with my ISAPI application. I created a new App Pool for the scripts directory and I notice that sometimes my dll is cached (and sometimes it's not). I ALWAYS want to cache the dll and the related files, so I tried setting the MaxCachedFileSize registry entry to a higher value, but the problem persists.

How do I force work process to always cache the dll?

The number entered in MaxCachedFileSize is bytes? or kbytes?

Thanks.

Answer:

By default, IIS6 caches the ISAPI Extension DLL on first access of the DLL.  IIS6 has no way to cache "related files" used by the ISAPI DLL unless the files are directly served by IIS.

In other words, MaxCachedFileSize has nothing to do with caching ISAPI DLLs nor its related files, so do not fiddle around with it. Can you provide the documentation which told you to change these settings for your issue?

The configuration which controls whether IIS caches the ISAPI Extension DLL or not is the "Cache ISAPI applications" checkbox inside of the "App Mappings" tab of the "Configuration" button inside the "Home Directory" tab of the website/vdir right-click Properties page. It is set by default and should remain set by default.

Response:

> Can you provide the documentation which told you
> to change these settings for your issue?

The IIS 6, but obviously I got confussed.

The fact is that, sometimes, IIS does not cache the ISAPI library and retains access to DLL. I mean: If I try to delete or replace the .dll file access is denied (until I recycle the app pool). So... this is my idea:

1) IIS always cache DLL so
2) The dll is always in memory (access to file is not denied)
3) If I want to replace the DLL by a newer version I simple copy
4) To let the new version start working I recycle the app pool

Thanks!

My Response:

Ah, I see where you are getting confused with concepts and terminology. Let me try to explain what is going on and how to accomplish what you are describing.

What you are trying to accomplish is to replace an in-use ISAPI DLL (i.e. one that has been loaded and used on the server). Typical situations which require this are:

  1. You are developing and debugging the ISAPI DLL, so you want to load and trigger the ISAPI DLL for testing, then replace the ISAPI DLL with an update and repeat.
  2. You are running a website that uses the ISAPI DLL but you want to update the ISAPI DLL without necessarily bringing the entire application/website down.

Where you are getting confused is your incorrect assumption that "If IIS caches the ISAPI DLL in memory, then access is not retained on the DLL file on disk and I can delete/replace it"... because the exact opposite is what actually happens. Thus, your idea does not work because it assumes several behaviors that simply does not exist.

IIS6 does not load ISAPI DLLs for execution until you make an explicit request which requires it. In fact, IIS6 does not even consume system resources to handle that request until it happens and demand starts the worker process to optimize and conserve system resources for the most popular activities.

When that first request involving the ISAPI DLL happens, IIS loads and retains the ISAPI DLL into memory (if "Cache ISAPI applications" is checked - by default), and the physical DLL file on disk is also locked so that it cannot be deleted/updated. This is why the "Cache ISAPI applications" checkbox exists - when it is unchecked, IIS does not leave the DLL loaded in memory and instead loads/unloads on every explicit request, so the physical file on disk is not locked and you can replace it with a newer version at any time as long as there is no request using it.

In other words, when debugging your ISAPI DLL and making frequent changes, you can uncheck "Cache ISAPI applications" and freely update the ISAPI DLL and test. On production systems, you want to leave that option checked because you do not frequently change the ISAPI DLL, and the constant DLL load/unload will drain server performance as well as expose startup/shutdown race condition bugs in ISAPI DLLs.

This gets to the issue of how to gracefully update an ISAPI DLL while a server is using it, and here is how to do it:

  1. Rename the existing ISAPI DLL to something else. NTFS allows you to rename the DLL and existing process with that DLL image loaded is still ok. This means existing in-flight requests continue using the old DLL.
  2. Copy over the new ISAPI DLL. New requests now use the new DLL. There is a slight race condition here, between when you rename the old DLL and copy over the new DLL, where requests will not see a DLL at all.
  3. At some future time, when requests using the old DLL complete and and your application pool recycles (so the DLL is unloaded from memory), you can delete the old renamed DLL.

Users/Applications won't notice anything different (application pool recycling does not break connections), but you just transparently updated the ISAPI DLL on the server...

//David

Comments

  • Anonymous
    February 01, 2006
    The comment has been removed

  • Anonymous
    February 01, 2006
    The comment has been removed

  • Anonymous
    March 12, 2006
    Question:
    Hello! I follow you blog daily. Good stuff!
    On my work I'm responsible for a web server,...

  • Anonymous
    May 04, 2006
    This is a wonderful wealth of information. Good Luck!

  • Anonymous
    March 14, 2008
    I use a lot of Isapi application on my websites. I also use Google Adsense to monetize my websites. The problem is, apparently Google always show "fix dll errors" ads when it's a page that is steamed directly from an Isapi (not a page saved to disk) This kind of defeats my purpose about whatever the site's actually about. Is there a way to rename my extension to like: .htm, then map to inetinfo.exe? I tried this but didn't get it to work. Any ideas? I just want to show more relevant ads when my pages streams from my ISAPIS. I would appreciate any assistance...

  • Anonymous
    March 17, 2008
    Dr Death - I hope you do see it from Google's perspective, that ignoring dynamically generated content makes sense because its content obviously changes -- so why cache/search it? It is likely to be wrong by the time it is searched by someone else. Now, it is certainly possible to create Application Mappings which wire extensions like .htm to be handled by ISAPI applications. For example, this is exactly how ASP works. Look at how .asp is configured and do something similar. //David

  • Anonymous
    April 27, 2009
    The comment has been removed