How can I make ADO database connections in 'TI

2020-04-15 04:09发布

TADOConnection is failing to connect in the application initialization section of Delphi ISAPI App (TISAPIApplication):

Application is built with Delphi XE SPI, running Win 7 64/IIS 7.5 and WinServer 2008 RS2 - it cannot connect with ADO in the global ISAPI application context. (Example code is using MS-SQLServer OLEDB - but we also fail using Sybase ASE provider.)

The following code fails when conn.Open is called - TADOConnection.open never returns - ISAPI app hangs in la-la land, no exception raised:

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.

The same code within a specific request handler (Delphi webAction) runs fine.

We suspect a problem with execution privileges in IIS at the ISAPI application level. But as far as we can tell, the entire IIS application stack from the webServer itself down to the specific virtual directory and the ISAPI dll itself are all running under the same credentials with same execution privileges.

Meanwhile, my workaround has been to initialize the database infrastructure from within an http response call (an ISAPI thread), and then simply check that it's initialized on each subsequent call. This works, but encumbers me with some constraints that I'd prefer not to deal with.

How can I make ADO database connections in a TISAPIApplication instance, before handling incoming requests.

2条回答
我欲成王,谁敢阻挡
2楼-- · 2020-04-15 04:31

I think the problem is that the code you run runs in the dll's main procedure. This part of the initialization is very restrictive e.g. you may not load any dll nor you are allowed to call CoInitialize (see http://msdn.microsoft.com/en-us/library/ms678543%28v=vs.85%29.aspx) . Your ActiveX alls there will cause some troubles which are most likely the reason for your exception.

查看更多
贪生不怕死
3楼-- · 2020-04-15 04:34

The begin ... end or an initialization part of a dll is the Delphi equivalent to dllmain in C++. So the same restrictions apply including:

  • Don't call CoInitialize
  • Don't call COM functions

This implies that you cannot create an ADO connection.

Do you know all the things that happen when you call TADOConnection.Create(Application);?

So what you're trying to do isn't going to work. And even if it did, you should not do it. Here's some better explanations:

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 creating the database connection in GetExtensionVersion. This is how your isapi dll is initialized. It is not just for reporting the extension version. So that is the way to go. Create your own GetExtensionVersion function that initializes your database and then call the previous Delphi function.

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.
查看更多
登录 后发表回答