Working with COM Components with
IIS 4.0 and Active Server Pages

by Rick Strahl, West Wind Technologies
http://www.west-wind.com/

last updated: December 27, 1997

Internet Information Server 4.0 has changed the rules on how COM objects are instantiated and a few changes have to be made from the procedures you might have used under IIS 3.0 when building and debugging your COM objects loaded from Active Server Pages.

Review of Active Server Components for use in VFP

Active Server Pages makes it possible to instantiate COM/Automation objects off an Active Server Page by using the Server.CreateObject("ProgId") syntax. This mechanism allows accessing any external components created by applications such as Visual FoxPro, Visual Basic and low level tools such as Visual C++ or Delphi. These components can be standard COM components or implement a few special methods to become Active Server Components. Active Server Components can access the ASP internal objects by receiving a reference to an Object Context that makes available the intrisic objects - Request, Response, Server, Application and Session.

COM Object Servers can be built as DLLs or EXE servers. ASP encourages use of InProcess DLL servers, but you can run EXE servers by setting a special registry key in IIS 3.0 (HKEY_LOCAL_MACHINE\SYSTEM\ CurrentControlSet\Services\W3SVC\ASP\ Parameters\ASPAllowOutofProcCmpnts) or a MetaBase entry (ASPAllowOutOfProcComponents set on either the Root or specific virtual directory see ).  There are serious limitations in regards to scalability with Visual FoxPro Automation servers, but any components built as InProcess objects built to the Apartment Model thread model (or 'Both' Apartment or Free threaded) works well and can scale with multiple simultaneous instances. VFP supports neither of these models and allows only single threaded access to Components. This limitation will be addressed in Visual FoxPro 6.0 by Microsoft.

To implement an Active Server Component the component should have a OnStartPage method at least and optionally an  OnEndPage method. OnStartPage passes an ObjectContext parameter that exposes the other objects. Here's a simple example of a Visual FoxPro implementation of the method:

DEFINE CLASS cASPComponent AS CUSTOM

oObjectContext = .NULL.

FUNCTION OnStartPage
LPARAMETER loObjectContext
IF TYPE("loObjectContext") = "O"
  THIS.oObjectContext = loObjectContext
ENDIF
RETURN
ENDDEFINE

It's now possible to get a reference to any of the ASP built in objects in a method like this:

loRequest = THIS.oObjectContext.Request

lcBrowser = loRequest.ServerVariables("HTTP_USER_AGENT").item()
lcFormVar=loRequest.Form("FormVarName").Item()

Although you can implement the OnStartPage() and OnEndPage() methods they're not required. Even if you need access to various objects of ASP you may not need these methods. You can also directly pass these objects to your server methods as parameters.

The new Security Model in IIS 4.0

IIS 3.0 had a simple security model that used the IUSR_ account of the local machine to impersonate any Automation object created by ASP. This means that Automation servers are very limited as the IUSR_ account has very few rights. While you can change permissions on this account it's not recommended since all Internet users come in under this account and too many rights can be a serious security risk to your Web site. Out Of Process Automation servers have the option of overriding security settings by using DCOMCnfg to configure the Automation server to a specific user impersonation.

IIS 4.0 introduces a new security model where Applications run under several accounts and services that are active simultaneously. The InetInfo Service now consists of the IISAdmin service and the other specific functional services such as Web, FTP and Gopher servers. In order to totally shut down IIS you need to kill both the Web Server (and FTP server if it's running as well) and the IISAdmin service.

In addition the ISAPI subsystem (ASP is an ISAPI extension and runs under the ISAPI subsystem) runs inside of Transaction Server. It is now possible to isolate individual applications to run in their own address space inside of a separate Transaction Server session. This allows the session to be shut down independently of the Web server and any badly behaved code will only crash the MTS session (which will retry to restart itself 5 times) and not the entire Web server.

This reliance on Transaction Server brings with it advantages and changes in the way you have to configure your servers.

DLL In Process Servers

  • Active Server loads InProcess (DLL) COM components and keeps them in memory, always. This means if you're building and debugging your component you cannot rebuild it as the component is in use.
  • To work around this set up your ASP application in a virtual directory and mark it to run 'Separate Memory Space' in the IIS Admin Console. 
    When you do, DLL servers can now be unloaded by right clicking on 'Properties' and then clicking on the Unload button on the Virtual Directory|Application Settings tab.
  • DLL components always run under the IUSR_ account and cannot not be configured externally to run under another account. You can however use the API to use the various Impersonation API calls to change the user account inside of your component code (Note this is very difficult to do in native VFP and you'll likely have to create a DLL or component in C to do this efficiently).

EXE Out Of Process Servers

  • EXE Out Of process Servers must have the ASPAllowOutOfProcComponents MetaBase Key set in order to work. See IISAdmin.htm for details on how to accomplish this.
  • Unlike IIS 3.0 EXE servers need to be configured with DCOMCnfg. This utility sets the Impersonation of an Automation Server. You need to set the Impersonation to an account that has rights to launch the server. Preferably use the Interactive User (if the machine is logged on) or else use an Admin account (it's safe since it's a server component that's not accessed by users directly).

 

Debugging tips for Automation Servers
You can use VisualFoxPro.Applicaction and its EVAL() method to call a Program file. Use the program file to instantiate your class and pass parameters along to the appropriate methods. This way you can 'interactively' debug servers. Unfortunately, you can't pass objects or long strings that way but for simple parms it should work.

For example you can do oServer.Eval("ASPDebug('Parm1','Parm2')") from within VBScript. You then create a program file called ASPDebug somewhere in your VFP default path. it might look like this:

PROCEDURE ASPDebug
LPARAMETER lcParm1, lcParm2
SET STEP ON
oServer = CREATE("MyClass")
oServer.MyMethod(lcParm1, lcParm2)

lvResult = oServer.SomePropertyOfServer
RETURN lvResult

This routine serves as a simple wrapper that calls your component as a straight VFP class. The key here is that you're instantiating the Visual FoxPro development environment and therefore can debug the code by setting a breakpoint.