【问题标题】:Running Classic ASP on IIS 7.5 in STA在 STA 中的 IIS 7.5 上运行经典 ASP
【发布时间】:2014-06-13 09:59:01
【问题描述】:

尝试通过启用 AspCompat 使 IIS 7.5 上的经典 ASP webapp 在 STA 模式下运行。这是一个硬性要求,因为实例化的 COM 对象不是线程安全的。

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

虽然设置是通过 AspCompat 强制设置的,但呈现网站时的行为似乎没有结果。

预期行为:

  1. 在每次页面请求时,ComServer.exe 都会启动、执行一些工作并关闭。
  2. 当另一个请求到达时,处理等待第一个请求完成。

我知道这是糟糕的表现。然而遗憾的是,这是运行旧版 ComServer 的一项硬性要求。

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

  1. 每批请求后,ComServer 都会关闭。
  2. 如果只有一个请求,则 ComServer 在请求后停止
  3. 如果有多个请求,都在同一个 ComServer 下处理

操作 3 有时会导致 ComServer 失败,从而导致 COMExceptions。

虽然问题可能是由于 COMObject 的设计不当造成的,但我无法更改。我唯一能做的就是使用应用程序锁来围绕 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 中实例化,如示例中所示。但是,这不会改变从其他客户端访问页面时的行为。

【问题讨论】:

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


    【解决方案1】:

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

    浏览到 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。

    【讨论】:

    • 感谢您的快速回复。不幸的是,这并没有改变我们案例中的行为。如果同时发出多个请求,ComServer 仍会被重用。我们还有什么可以尝试的吗?
    • 嗨,Ramon Bertrand,据我所知,按照上述参数,我们可以在 IIS 7.5 上设置经典的 asp。您可以更改 applicationHost.config 上的配置
    • 我已应用这些设置并确认它们在 IIS 重置后处于活动状态。页面像以前一样呈现得很好。但是,来自不同客户端的多个同时请求的 STA 问题仍然存在。
    【解决方案2】:

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

    但是,如果您以示例格式编写类似这样的内容来获得想法。

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

    那么您将需要按如下方式使用 Lock 和 Unlock:

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

    这是因为线程可能在读取和写入 Application 对象之间被中断,因此另一个线程可能会更改为“计数器”存储的值。

    【讨论】:

    • 再次感谢您。我不知道如何将这与我们的情况联系起来。我认为我这边需要更多信息。我已经更新了这个问题。请发现现在包含对象实例化。我该如何应用这个答案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    相关资源
    最近更新 更多