简体   繁体   中英

Running Classic ASP on IIS 7.5 in STA

Trying to for a Classic ASP webapp on IIS 7.5 to run in STA mode by enabling AspCompat. This is a hard requirement due to a COM Object being instantiated that is not thread safe.

<%@ Page Language="VBScript" AspCompat="true" Debug="false" %>

Although the settings is forced through AspCompat, the behaviour when rendering websites seems not to be consequent.

The expected behaviour:

  1. On every page request, the ComServer.exe starts, does some work and closes.
  2. When another request arrives, processing waits for the first request to finish.

I know this is bad performance whise. However sadly, this is a hard requirement for running the legacy ComServer.

This behaviour is visible when there are multiple parallel requests comming from the same client. When multiple requests come from different clients however, the behaviour changes:

  1. After every batch of requests, the ComServer is closed.
  2. If there is only one request, the ComServer is stopped after the request
  3. If there are multiple requests, they are all processed under the same ComServer

Action 3 causes the ComServer to sometimes fail, causing COMExceptions.

Although the issue is probably caused by bad design of the COMObject, I cannot change this. The only thing I can do is surrounding COMObject access with an Application Lock

Dim oComSvr as object
oComSvr=Server.CreateObject("com_svr.my_svr")
...
Application.Lock
returnValue=oComSvr.selectform(value1, value2, ...)
Application.Unlock

However this prevents most COMExceptions, there are still specific timings that result in a COMException.

What can I do to force constant STA behaviour, also if multiple requests to the same IIS server come from different clients.

Tried to follow this article and implemented Page_Load to prevent the object being created before STA mode. http://technet.microsoft.com/en-ca/zwk9h2kb(v=vs.95).aspx

It still looks like if AspCompat is being ignored.

[COMException (0x800706be): Creating an instance of the COM component with CLSID {B28A581A-6CE3-46E9-871F-B2E129F7D238} from the IClassFactory failed due to the following error: 800706be.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +86
   System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +230
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +67
   System.Activator.CreateInstance(Type type) +6
   System.Web.HttpServerUtility.CreateObject(String progID) +122
   ASP.myapp.Page_Load() +1670
   System.Web.Util.CalliHelper.ArglessFunctionCaller(IntPtr fp, Object o) +8
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +8760147
   System.Web.UI.Control.OnLoad(EventArgs e) +99
   System.Web.UI.Control.LoadRecursive() +50
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627

Update: Read here and here that it is important WHERE the STA object is instantiated. Instantiating the object during construction time will cause this issue. http://technet.microsoft.com/en-ca/zwk9h2kb(v=vs.95).aspx http://msdn.microsoft.com/en-us/library/5dws599a(vs.71).aspx

Tried instantiating in Page_Load as in the example. However this does not change the behaviour when accessing the page from another client.

OK we've had this and this is how I've found a solution.. In our case I think it was linked to parent paths but could have been session state too...

Browse to C:\\Documents and Settings\\$your user name$\\My Documents\\IIS 7.5\\config

Open applicationHost.config

Find the section

Change the section to the following… By default it only had the cache and empty limits bits but feel free to adjust any parameters you don't want.

<asp 
     enableParentPaths="true" 
     bufferingOn="true" 
     errorsToNTLog="true" 
     appAllowDebugging="true" 
     appAllowClientDebug="true" 
     scriptErrorSentToBrowser="true">

   <session allowSessionState="true" />
   <cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" />
   <limits />
</asp>

Save and restart iis 7.5.

if it is surrounding COMObject access with an Application Lock

However, if you write something like this in a sample format to get an idea.

Application["Counter"] = (int) Application["Counter"] + 1;

then you will need to use Lock and Unlock as follows:

 Application.Lock();
 Application["Counter"] = (int) Application["Counter"] + 1;
 Application.Unlock();

This is because the thread might be interrupted between the read from, and then write to, the Application object, and another thread could therefore alter the value stored for the "Counter".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM