在STA中的IIS 7.5上运行经典ASP

时间:2014-06-13 09:59:01

标签: iis asp-classic com iis-7.5 visual-foxpro

尝试通过启用AspCompat使IIS 7.5上的经典ASP Web应用程序在STA模式下运行。由于实例化的COM对象不是线程安全的,因此这是一个很难的要求。

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

虽然通过AspCompat强制设置,但渲染网站时的行为似乎不会成为结果。

预期的行为:

  1. 在每个页面请求中,ComServer.exe启动,执行一些操作并关闭。
  2. 当另一个请求到达时,处理等待第一个请求完成。
  3. 我知道这是糟糕的表现。但遗憾的是,这是运行传统ComServer的一项艰难要求。

    当有多个并行请求来自同一客户端时,此行为可见。但是,当多个请求来自不同的客户端时,行为会发生变化:

    1. 在每批请求之后,ComServer将关闭。
    2. 如果只有一个请求,则在请求后停止ComServer
    3. 如果有多个请求,则它们都在同一个ComServer下处理
    4. 操作3导致ComServer有时会失败,从而导致COMExceptions。

      虽然问题可能是由于COMObject的设计不好引起的,但我无法改变这一点。我唯一能做的就是使用Application Lock围绕COMObject访问

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

      但是这会阻止大多数COMExceptions,但仍然存在导致COMException的特定时序。

      如果对同一IIS服务器的多个请求来自不同的客户端,我该怎么做才能强制执行常量STA行为。

      试图遵循本文并实现Page_Load以防止在STA模式之前创建对象。 http://technet.microsoft.com/en-ca/zwk9h2kb(v=vs.95).aspx

      如果忽略AspCompat,看起来仍然如此。

      [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
      

      更新: 在这里和这里阅读重要的是STA对象被实例化。在施工期间实例化对象将导致此问题。 http://technet.microsoft.com/en-ca/zwk9h2kb(v=vs.95).aspx http://msdn.microsoft.com/en-us/library/5dws599a(vs.71).aspx

      尝试在Page_Load中实例化,如示例中所示。但是,这不会改变从其他客户端访问页面时的行为。

2 个答案:

答案 0 :(得分:0)

好的,我们已经有了这个,这就是我找到解决方案的方法..在我们的案例中,我认为它与父路径相关联,但也可能是会话状态......

浏览到C:\ Documents and Settings \ $您的用户名$ \ My Documents \ IIS 7.5 \ config

打开applicationHost.config

找到

部分

将该部分更改为以下内容...默认情况下,它只有缓存和空限制位,但您可以随意调整任何不需要的参数。

<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>

保存并重新启动iis 7.5。

答案 1 :(得分:0)

如果它是围绕使用应用程序锁的COMObject访问

但是,如果你以样本格式写这样的东西来获得一个想法。

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

然后您将需要使用锁定和解锁,如下所示:

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

这是因为线程可能在Application对象的读取和写入之间被中断,因此另一个线程可能会改变为&#34; Counter&#34;存储的值。