Compartir a través de


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 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 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 , 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 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.

    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, 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
      
    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 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.

    3. Vaya 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 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 de OLEComponent.Object.1. El que está al 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 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ún ThreadingModel 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.

    5. 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.

    6. 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.

    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 insertó 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, esto informa a DCOM para ejecutar el archivo ejecutable predeterminado, dllhost.exe y cargar el objeto COM dentro de su espacio de proceso.

    9. 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.

    10. 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 registrada

      Informació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 servidor

    11. Pruebe 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
      

Referencias

Procedimientos almacenados de OLE Automation (Transact-SQL)