在处理传入请求之前,如何在'TISAPIApplication`中建立ADO数据库连接?

时间:2011-08-31 22:15:26

标签: delphi iis iis-7.5 ado isapi

TADOConnection无法在Delphi ISAPI App(TISAPIApplication)的应用程序初始化部分进行连接:

应用程序使用Delphi XE SPI构建,运行Win 7 64 / IIS 7.5和WinServer 2008 RS2 - 它无法在全局ISAPI应用程序上下文中与ADO连接。 (示例代码使用MS-SQLServer OLEDB - 但我们也无法使用Sybase ASE提供程序。)

以下代码在调用conn.Open时失败 - TADOConnection.open永远不会返回 - ISAPI应用程序在la-la land中挂起,没有异常引发:

library ISAPIBareBones;

uses
  ActiveX,
  ADODB,

    (...)

var
  conn: TADOConnection;

begin

  CoInitFlags := COINIT_MULTITHREADED;
  Application.Initialize;

  coinitialize(nil);
  conn := TADOConnection.Create(Application);
  conn.ConnectionString := 'Provider=SQLOLEDB.1;xxx';

//Fails here:

  try
    conn.Open;
  except on e:exception do
    logException(e)
  end;


  Application.WebModuleClass := WebModuleClass;
  Application.Run;

end.

特定请求处理程序(Delphi webAction)中的相同代码运行正常。

我们怀疑ISAPI应用程序级别的IIS中的执行权限存在问题。但据我们所知,从webServer本身到特定虚拟目录的整个IIS应用程序堆栈和ISAPI dll本身都在具有相同执行权限的相同凭据下运行。

与此同时,我的解决方法是从http响应调用(ISAPI线程)中初始化数据库基础结构,然后检查它是否在每次后续调用时初始化。这样做有效,但是让我感到困扰的是一些我不愿意处理的限制。

在处理传入请求之前,如何在TISAPIApplication实例中建立ADO数据库连接。

2 个答案:

答案 0 :(得分:3)

dll的begin ... endinitialization部分是Delphi,相当于C ++中的dllmain。因此适用相同的限制包括:

  • 不要打电话给CoInitialize
  • 不要调用COM功能

这意味着您无法创建ADO连接。

您是否知道致电TADOConnection.Create(Application);时发生的所有事情?

所以你要做的就是不去工作。即使它确实如此,你也不应该这样做。这里有一些更好的解释:

http://msdn.microsoft.com/en-us/library/ms682583%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/63401.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2004/01/28/63880.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2014/08/21/10551659.aspx

MSDN suggests在GetExtensionVersion中创建数据库连接。这就是你的isapi dll初始化的方式。它不仅仅用于报告扩展版本。这就是要走的路。创建自己的GetExtensionVersion函数,初始化数据库,然后调用以前的Delphi函数。

library Project1;

uses
  Winapi.ActiveX,
  System.Win.ComObj,
  Web.WebBroker,
  Web.Win.ISAPIApp,
  Web.Win.ISAPIThreadPool,
  Winapi.Isapi2,
  Winapi.Windows,
  WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule};

{$R *.res}

function GetExtensionVersion(var Ver: THSE_VERSION_INFO): BOOL; stdcall;
begin
  Result := Web.Win.ISAPIApp.GetExtensionVersion(Ver);
  // create your ado connection here
end;


exports
  GetExtensionVersion,
  HttpExtensionProc,
  TerminateExtension;

begin
  CoInitFlags := COINIT_MULTITHREADED;
  Application.Initialize;
  Application.WebModuleClass := WebModuleClass;
  Application.Run;
end.

答案 1 :(得分:2)

我认为问题在于你运行的代码在dll的主程序中运行。这部分初始化是非常严格的,例如你也许不会加载任何dll 允许调用CoInitialize(参见http://msdn.microsoft.com/en-us/library/ms678543%28v=vs.85%29.aspx)。 你的ActiveX alls会导致一些麻烦,这很可能是你的原因 异常。