delphi - ¿Cómo puedo hacer conexiones de bases de datos ADO en ''TISAPIApplication` antes de procesar las solicitudes entrantes?
iis iis-7.5 (2)
TADOConnection
no se puede conectar en la sección de inicialización de la aplicación de Delphi ISAPI (aplicación TISAPIApplication
):
La aplicación está desarrollada con Delphi XE SPI, ejecutando Win 7 64 / IIS 7.5 y WinServer 2008 RS2 - no se puede conectar con ADO en el contexto de la aplicación ISAPI global. (El código de ejemplo usa MS-SQLServer OLEDB, pero también fallamos al usar el proveedor ASE de Sybase).
El siguiente código falla cuando se llama a TADOConnection.open
- TADOConnection.open
nunca regresa - La aplicación ISAPI se cuelga en la tierra de la-la, sin excepción:
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.
El mismo código dentro de un manejador de solicitudes específico (Delphi webAction) funciona bien.
Sospechamos que hay un problema con los privilegios de ejecución en IIS en el nivel de aplicación ISAPI. Pero, por lo que podemos decir, toda la pila de aplicaciones IIS desde el servidor web hasta el directorio virtual específico y el dll ISAPI se están ejecutando bajo las mismas credenciales con los mismos privilegios de ejecución.
Mientras tanto, mi solución ha sido inicializar la infraestructura de la base de datos desde una llamada de respuesta http (un hilo ISAPI), y luego simplemente verificar que se haya inicializado en cada llamada posterior. Esto funciona, pero me impone algunas limitaciones con las que prefiero no tratar.
¿Cómo puedo hacer conexiones de bases de datos ADO en una instancia TISAPIApplication
, antes de manejar las solicitudes entrantes.
Creo que el problema es que el código que ejecuta se ejecuta en el procedimiento principal de la dll. Esta parte de la inicialización es muy restrictiva, por ejemplo, no puede cargar ningún dll ni puede llamar a CoInitialize (consulte http://msdn.microsoft.com/en-us/library/ms678543%28v=vs.85%29. aspx ). Sus alls de ActiveX causarán algunos problemas que probablemente sean el motivo de su excepción.
El begin ... end
o una parte de initialization
de un dll es el equivalente de Delphi a dllmain en C ++. Por lo tanto, se aplican las mismas restricciones, que incluyen:
- No llame a CoInitialize
- No llame a las funciones COM
Esto implica que no puede crear una conexión ADO.
¿Conoce todas las cosas que suceden cuando llama a TADOConnection.Create(Application);
?
Entonces, lo que estás tratando de hacer no va a funcionar. E incluso si lo hiciera, no deberías hacerlo. Aquí hay algunas explicaciones mejores:
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 sugiere crear la conexión de base de datos en GetExtensionVersion. Así es como se inicializa su isapi dll. No es solo para informar la versión de la extensión. Entonces ese es el camino a seguir. Cree su propia función GetExtensionVersion que inicialice su base de datos y luego llame a la función Delphi anterior.
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.