Ejecución de un objeto COM basado en DLL fuera del proceso de SQL Server
En este artículo se describe cómo ejecutar un objeto COM basado en DLL fuera del proceso de SQL Server.
Versión del producto original: SQL Server
Número de KB original: 198891
Resumen
Microsoft SQL Server proporciona la capacidad de cargar y ejecutar objetos de modelo de objetos componentes personalizados (COM) a través de un conjunto de procedimientos almacenados de Automatización OLE o a través de procedimientos almacenados extendidos. De forma predeterminada, los objetos COM basados en DLL se cargan como en el servidor de procesos, lo que significa que los objetos COM no solo se cargan dentro del espacio de direcciones de memoria del proceso de SQL Server, sino que también tienen acceso completo a este espacio de direcciones de memoria. Por lo tanto, un objeto COM cargado en el espacio de proceso de SQL Server debe cumplir las mismas reglas que cualquier archivo DLL. Existe la posibilidad de que un objeto COM sobrescriba la memoria dentro del proceso de SQL Server o filtre los recursos, lo que provoca inestabilidad.
Si hay sospechas de que un objeto COM puede estar afectando a la solidez del proceso de SQL Server, es posible que desee usar los pasos descritos en este artículo para crear instancias del objeto COM fuera del espacio de proceso de SQL Server. La implementación de la especificación del modelo de objetos de componente distribuido (DCOM) de Transparencia de ubicación en el sistema operativo ha proporcionado la capacidad de ejecutar un objeto COM basado en DLL fuera del espacio de proceso de SQL Server.
El proceso de ejecutar un objeto COM basado en DLL fuera del espacio de direcciones de la aplicación principal se denomina comunicación remota. La comunicación remota requiere que otro ejecutable sea un proceso suplente en lugar del ejecutable de SQL Server. El archivo ejecutable predeterminado usado por DCOM Service Control Manager (rpcss.exe) se denomina dllhost.exe. La estructura de compatibilidad de DCOM usa el archivo dllhost.exe para cargar el archivo DLL en su espacio de proceso y, a continuación, usa pares proxy/código auxiliar para serializar la interfaz solicitada de forma transparente en el cliente, que en este caso es SQL Server. Este ejecutable puede aceptar varias solicitudes de interfaz o método simultáneamente. Una vez completada la utilización de la interfaz, DCOM Service Control Manager (SCM) administra la limpieza y descarga del archivo dllhost.exe . No se debe esperar que los objetos COM conserven la información de estado entre las instancias.
Los pasos siguientes se pueden aplicar a cualquier objeto COM basado en DLL que se cree en el espacio de procesos de SQL Server, tanto si se crea una instancia a través sp_OACreate
de un procedimiento almacenado extendido como si se está creando.
Más información
A continuación se muestra información sobre los dos métodos básicos que puede usar para crear instancias del objeto COM fuera del proceso.
El cliente COM solicita comunicación remota del objeto
Al cambiar la forma en que se invoca el objeto COM, puede solicitar que el objeto se cree fuera del espacio de direcciones de SQL Server.
Si el objeto COM se carga mediante el
sp_OACreate
procedimiento , de forma predeterminada se carga en proceso. Sin embargo, hay un tercer parámetro opcional para este procedimiento que puede usar para indicar el contexto de dónde crear el objeto. Si no se especifica este parámetro, se usa el valor predeterminado de cinco (5), lo que significa ejecutar el objeto dentro o fuera del proceso. Debe cambiar el parámetro a cuatro (4), lo que indica a DCOM que este componente se va a ejecutar como un archivo ejecutable local. Use la sintaxis similar al ejemplo siguiente para informar explícitamente a DCOM de que ejecute el objeto COM fuera del proceso mediante elsp_OACreate
procedimiento almacenado:DECLARE @object int DECLARE @hr int EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
Si el objeto COM se crea dentro de un procedimiento almacenado extendido, el tercer parámetro de
CoCreateInstance
oCoCreateInstanceEx
se puede cambiar aCLSCTX_LOCAL_SERVER
. Esto se muestra en el ejemplo de código siguiente medianteCoCreateInstance
:HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&piunknown);
Modificación del registro para forzar la comunicación remota del objeto
Si no puede modificar el cliente COM para solicitar que el objeto se cree fuera del proceso, existen dos métodos diferentes para forzar la creación del objeto fuera del proceso.
Use el visor de objetos OLE/COM (oleview.exe) que se incluye con Visual C++ y busque el ProgID en forma de
OLEComponent.Object
Todos los objetos. Seleccione el objeto COM y, a continuación, en el menú Objeto , seleccioneCoCreateInstance
Marcas. Asegúrese de que soloCLSCTX_LOCAL_SERVER
está seleccionado. A continuación, en las pestañas Implementación e Inproc Server , seleccione Usar proceso suplente y deje en blanco la ruta de acceso al suplente personalizado, lo que permite cargar el archivo dllhost.exe y la DLL COM que se incluye en su espacio de proceso.Siga estos pasos para actualizar manualmente el registro.
Advertencia
Si modifica el Registro de forma incorrecta mediante el Editor del Registro o con otro método, podrían producirse graves problemas. Estos problemas pueden requerir que reinstale el sistema operativo. Microsoft no puede garantizar que estos problemas se puedan solucionar. Modifique el Registro bajo su propia responsabilidad.
Obtenga el identificador de clase (CLSID) del objeto COM. CLSID es un número de 128 bits y se considera un identificador único global (GUID) que se usa para identificar de forma única el componente, el módulo o el archivo que contiene este objeto COM. Al crear objetos COM mediante los procedimientos almacenados de OLE Automation, el primer parámetro para el procedimiento almacenado es un identificador de programación o el ProgID del objeto OLE se usa para derivar el CLSID. Esta cadena de caracteres describe la clase del objeto OLE y tiene la siguiente forma:
OLEComponent.Object
Puede usar el identificador de programación para buscar el identificador de clase de un objeto COM.
Abra el Editor del Registro (regedit.exe) y, en la
HKEY_CLASSES_ROOT
clave, use elFind
método para buscar una clave con el nombre de <OLEComponent.Object>. Lo encontrará en otros niveles, pero debe encontrarse en el nivel directamente debajo deHKEY_CLASSES_ROOT
. Después de buscar la clave, expanda la carpeta para el nombre de la clave y debería ver una subclave denominada CLSID. Seleccione esa carpeta para ver los valores de esa clave. En el lado derecho de la pantalla hay un título denominado Default. Los datos de esa clave deben tener el formato siguiente:{59F929A0-74D8-11D2-8CBC-08005A390B09}
Anote este valor o cópielo en el Bloc de notas. Incluya los corchetes.
Vaya bajo la
HKEY_CLASSES_ROOT\CLSID
clave y busque la subclave con este número GUID. Después de resaltar laHKEY_CLASSES_ROOT\CLSID
clave, puede usar la función Buscar en el Editor del Registro (en el menú Editar ) y pegar el GUID en el cuadro de diálogo Buscar . Asegúrese de que ha encontrado la interfaz adecuada inspeccionando la subclave InprocServer32 en esta clave, que apunta a la ubicación del archivo DLL COM. Si hay una clave TypeLib, compruebe este valor GUID. Debe ser diferente de lo que anotó en el paso 1. De lo contrario, tiene el GUID de TypeLib y no el GUID para el objeto COM. La subclave ProgID tendrá un valor deOLEComponent.Object.1
. El que está al final es solo para este ejemplo y se usa para la información de control de versiones.Mientras se encuentra en la subclave InprocServer32 del GUID, asegúrese de que existe un
ThreadingModel
valor y de que está establecido en Both o Free para asegurarse de que la serialización comprende el modelo de subproceso del objeto COM para habilitar la ejecución de COM fuera del espacio de proceso de SQL Server. Si no hay ningúnThreadingModel
valor o se establece en Apartment, es posible que la creación de instancias de objeto COM no sea coherente.Nota:
Si agrega el
ThreadingModel
valor, asegúrese de probar el objeto COM antes de implementarlo.Resalte el número de GUID o la subclave en la
HKEY_CLASSES_ROOT\CLSID
clave. En el menú Editar , seleccione Nuevo y, a continuación, seleccione Valor de cadena. En la columna Nombre , escriba AppID.Presione ENTRAR y, a continuación, inserte el identificador de clase o el número GUID que anotó en el paso 1 como valor. El GUID debe estar dentro de los corchetes como en el ejemplo siguiente:
{59F929A0-74D8-11D2-8CBC-08005A390B09}
DCOM usa el identificador de aplicación AppID para asociar el archivo DLL a un archivo ejecutable.
Agregue una nueva subclave bajo
HKEY_CLASSES_ROOT\AppID
y establezca su nombre en el mismo identificador de clase o número GUID con los corchetes que insertó en el paso anterior.Resalte el nombre del GUID. En el menú Editar , seleccione Nuevo y, a continuación, seleccione Valor de cadena. En la columna Nombre , escriba dllSurrogate.
Deje la columna Datos en blanco para este valor. Dado que la columna de datos está en blanco, esto informa a DCOM para ejecutar el archivo ejecutable predeterminado, dllhost.exe y cargar el objeto COM dentro de su espacio de proceso.
Cierre el Editor del registro. Haga clic en Inicioy, a continuación, seleccione Ejecutar. En el cuadro de diálogo Ejecutar , escriba DCOMCNFG.
Presione la tecla ENTRAR para abrir el cuadro de diálogo Propiedades de configuración COM distribuidas. Haga clic en la pestaña Propiedades predeterminadas y asegúrese de que habilitar COM distribuido en este equipo está seleccionado. Si no es así, selecciónelo y, a continuación, seleccione Aplicar.
Asegúrese de que la cuenta de usuario de Windows NT en la que se ejecuta SQL Server tiene permiso control total en las claves del Registro para este objeto. Si los permisos no son suficientes o las claves del Registro no son suficientes, pueden producirse los errores siguientes al crear el objeto COM:
Información de error de AUTOMATIZACIÓN OLE
HRESULT: 0x80040154
Fuente: Procedimiento extendido ODSOLE
Descripción: Clase no registradaInformación de error de AUTOMATIZACIÓN OLE
HRESULT: 0x80070005
Fuente: Procedimiento extendido ODSOLE
Descripción: se deniega el acceso.Información de error de AUTOMATIZACIÓN OLE
HRESULT: 0x80080005
Fuente: Procedimiento extendido ODSOLE
Descripción: Error en la ejecución del servidorPruebe y compruebe si se ejecuta el archivo dllhost.exe y carga el objeto COM en su espacio de proceso. Esto requiere que el Kit de recursos de Windows NT esté en el equipo Windows NT en el que se ejecuta SQL Server. Abra un símbolo del sistema y, desde el símbolo del sistema, ejecute el archivo tlist.exe , que muestra todos los procesos y sus identificadores de proceso asociados o Identificadores de proceso (PID). En el script de Transact-SQL donde
sp_OACreate
se ejecuta y después de que se ejecute esa llamada, pero antes de que finalice el script, use lo siguiente para retrasar la finalización del script durante 20 segundos adicionales:WAITFOR DELAY '000:00:20'
Ejecute el script e vaya inmediatamente al símbolo del sistema y ejecute el archivo tlist.exe . Anote el DLLHOST.EXE PID. Vuelva a ejecutar tlist.exe y pase el PID como parámetro. Esto muestra los archivos DLL que se cargan dentro del espacio de proceso de dllhost.exe . El objeto COM basado en DLL debe aparecer como en ejecución en este proceso. Una vez devuelto el script, la ejecución de tlist.exe de nuevo revela que el proceso de dllhost.exe ya no se está ejecutando.
En la siguiente salida de ejemplo, ADODB. El objeto connection se crea fuera del espacio de proceso de SQL Server. Esta instantánea que usa tlist.exe se realizó mientras el objeto COM existía en el espacio de proceso dllhost.exe . Observe que el módulo msado15.dll, que es el módulo que contiene el objeto COM, se carga.
C:\>tlist dllhost 275 dllhost.exe CWD: C:\NT40\system32\ CmdLine: C:\NT40\System32\dllhost.exe {00000514-0000-0010-8000-00AA006D2EA4} -Embedding VirtualSize: 19180 KB PeakVirtualSize: 19180 KB WorkingSetSize: 1780 KB PeakWorkingSetSize: 1780 KB NumberOfThreads: 3 278 Win32StartAddr:0x01001920 LastErr:0x00000000 State:Waiting 215 Win32StartAddr:0x00001b5e LastErr:0x00000000 State:Waiting 253 Win32StartAddr:0x00001b60 LastErr:0x000000cb State:Waiting 4.0.1381.105 shp 0x01000000 dllhost.exe 4.0.1381.130 shp 0x77f60000 ntdll.dll 4.0.1381.121 shp 0x77dc0000 ADVAPI32.dll 4.0.1381.133 shp 0x77f00000 KERNEL32.dll 4.0.1381.133 shp 0x77e70000 USER32.dll 4.0.1381.115 shp 0x77ed0000 GDI32.dll 4.0.1381.131 shp 0x77e10000 RPCRT4.dll 4.0.1381.117 shp 0x77b20000 ole32.dll 6.0.8267.0 shp 0x78000000 MSVCRT.dll 0x1f310000 msado15.dll 2.30.4265.1 shp 0x766f0000 OLEAUT32.dll 4.0.1381.72 shp 0x77bf0000 rpcltc1.dll