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 personalizados del modelo de objetos de componente (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 de proceso SQL Server, sino que también tienen acceso total a este espacio de direcciones de memoria. Por lo tanto, un objeto COM cargado en el espacio de proceso SQL Server debe cumplir las mismas reglas que cualquier archivo DLL. Existe la posibilidad de que un objeto COM pueda sobrescribir la memoria dentro del proceso de SQL Server o perder 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 de este artículo para crear una instancia del objeto COM fuera del espacio de proceso 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 SQL Server.

El proceso de ejecución de 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 SQL Server. El ejecutable predeterminado que usa DCOM Service Control Manager (rpcss.exe) se denomina dllhost.exe. La estructura de compatibilidad con 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 al cliente, que en este caso es el SQL Server. Este ejecutable puede aceptar varias solicitudes de interfaz o método simultáneamente. Una vez completado el uso 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 instancias.

Los pasos siguientes se pueden aplicar a cualquier objeto COM basado en DLL que se cree en el espacio de proceso de SQL Server, ya sea que se cree una instancia a través sp_OACreate de o un procedimiento almacenado extendido.

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 la comunicación remota del objeto

Al cambiar la forma en que invoca el objeto COM, puede solicitar que el objeto se cree fuera del espacio de direcciones SQL Server.

  • Si el objeto COM se carga mediante el sp_OACreate procedimiento , se carga de forma predeterminada 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 la configuración predeterminada 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 ejecutable local. Use una sintaxis similar al ejemplo siguiente para informar explícitamente a DCOM de que ejecute el objeto COM fuera de proceso mediante el sp_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 o CoCreateInstanceEx se puede cambiar a CLSCTX_LOCAL_SERVER. Esto se muestra en el ejemplo de código siguiente mediante CoCreateInstance:

    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 de 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 progID en forma de OLEComponent.Object en Todos los objetos. Seleccione el objeto COM y, a continuación, en el menú Objeto , seleccione CoCreateInstance Marcas. Asegúrese de que solo CLSCTX_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 el archivo DLL COM incluidos en su espacio de proceso.

  • Siga estos pasos para actualizar manualmente el registro.

    Advertencia

    Es posible que se produzcan problemas graves si modifica el Registro de forma incorrecta mediante el Editor del Registro u otro método. 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.

    1. 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, módulo o archivo que contiene este objeto COM. Al crear objetos COM mediante los procedimientos almacenados de OLE Automation, el primer parámetro del 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 el siguiente formato:

      OLEComponent.Object
      
    2. 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 el Find 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 de HKEY_CLASSES_ROOT. Después de buscar la clave, expanda la carpeta para el nombre de clave y debería ver una subclave denominada CLSID. Seleccione esa carpeta para ver los valores dentro de esa clave. En el lado derecho de la pantalla hay un título denominado Predeterminado. Los datos de esa clave deben tener el siguiente formato:

      {59F929A0-74D8-11D2-8CBC-08005A390B09}

      Anote este valor o cópielo en el Bloc de notas. Incluya los corchetes.

    3. Navegue bajo la HKEY_CLASSES_ROOT\CLSID clave y busque la subclave con este número GUID. Después de resaltar la HKEY_CLASSES_ROOT\CLSID clave, puede usar la función Buscar en el Registro Editor (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. Esto 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 de OLEComponent.Object.1. El del final es solo para este ejemplo y se usa para la información de control de versiones.

    4. Mientras se encuentra en la subclave InprocServer32 del GUID, asegúrese de que existe un ThreadingModel valor y de que está establecido en Ambos o Libre para asegurarse de que la serialización comprende el modelo de subprocesos del objeto COM para habilitar la ejecución de COM fuera de SQL Server espacio de proceso. Si no hay un ThreadingModel valor o se establece en Apartment, es posible que la creación de instancias de objetos COM no sea coherente.

      Nota:

      Si agrega el valor, asegúrese de probar el ThreadingModel objeto COM antes de implementarlo.

    5. Resalte el número GUID o la subclave debajo de 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.

    6. Presione ENTRAR e 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.

    7. 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 se insertaron en el paso anterior.

    8. 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, informa a DCOM de que ejecute el archivo ejecutable predeterminado, dllhost.exey cargue el objeto COM dentro de su espacio de proceso.

    9. Cierre el Editor del Registro. Haga clic en Inicio y, 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 distribuida . Haga clic en la pestaña Propiedades predeterminadas y asegúrese de que está seleccionada la opción Habilitar COM distribuida en este equipo. Si no es así, selecciónelo y, a continuación, seleccione Aplicar.

    10. Asegúrese de que la cuenta de usuario de Windows NT en la que se ejecuta SQL Server tiene el permiso Control total en las claves del Registro para este objeto. Si los permisos no son suficientes o las claves del Registro se introducen incorrectamente, pueden producirse los siguientes errores al crear el objeto COM:

      Información de error de Automatización OLE
      HRESULT: 0x80040154
      Origen: Procedimiento extendido de ODSOLE
      Descripción: clase no registrada

      Información de error de Automatización OLE
      HRESULT: 0x80070005
      Origen: Procedimiento extendido de ODSOLE
      Descripción: se deniega el acceso.

      Información de error de Automatización OLE
      HRESULT: 0x80080005
      Origen: Procedimiento extendido de ODSOLE
      Descripción: Error en la ejecución del servidor

    11. Pruebe y vea si está ejecutando el archivo dllhost.exe y cargando 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 inmediatamente vaya al símbolo del sistema y ejecute el archivo tlist.exe . Observe el PID dedllhost.exe . 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 dedllhost.exe . El objeto COM basado en DLL debe aparecer como en ejecución dentro de este proceso. Una vez devuelto el script, la ejecución detlist.exe de nuevo revela que el proceso dedllhost.exe ya no se está ejecutando.

      En la salida de ejemplo siguiente, ADODB. El objeto Connection se crea fuera del espacio de proceso SQL Server. Esta instantánea mediante tlist.exe se realizó mientras el objeto COM existía en el espacio de proceso dedllhost.exe . Observe que se carga el módulo msado15.dll, que es el módulo que contiene el objeto COM.

      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
      

Referencias

Procedimientos almacenados de Automatización OLE (Transact-SQL)