问题
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.
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/7264136/how-can-i-make-ado-database-connections-in-tisapiapplication-before-processing