Executar um objeto COM baseado em DLL fora do processo de SQL Server

Este artigo descreve como executar um objeto COM baseado em DLL fora do processo de SQL Server.

Versão original do produto: SQL Server
Número de KB original: 198891

Resumo

A Microsoft SQL Server fornece a capacidade de carregar e executar objetos COM (Component Object Model) personalizados por meio de um conjunto de procedimentos armazenados da Automação OLE ou por meio de procedimentos armazenados estendidos. Por padrão, objetos COM baseados em DLL são carregados como no servidor de processo, o que significa que os objetos COM não são carregados apenas dentro do espaço de endereço de memória de processo SQL Server, mas também têm acesso total a esse espaço de endereço de memória. Portanto, um objeto COM carregado no espaço de processo SQL Server deve seguir as mesmas regras que qualquer arquivo DLL. Há um potencial de que um objeto COM possa substituir a memória no SQL Server processar ou vazar recursos, causando instabilidade.

Se houver suspeita de que um objeto COM possa estar afetando a robustez do processo de SQL Server, talvez você queira usar as etapas neste artigo para instanciar o objeto COM fora do SQL Server espaço de processo. A implementação da especificação DCOM (Distributed Component Object Model) da Transparência de Localização no sistema operacional forneceu a capacidade de executar um objeto COM baseado em DLL fora do espaço de processo SQL Server.

O processo de execução de um objeto COM baseado em DLL fora do espaço de endereço do aplicativo main é chamado de remoção. A remoção requer que outro executável seja um processo substituto no lugar do SQL Server executável. O executável padrão usado pelo DCOM Service Control Manager (rpcss.exe) é nomeado dllhost.exe. A estrutura de suporte do DCOM usa o arquivo dllhost.exe para carregar a DLL em seu espaço de processo e, em seguida, usa pares proxy/stub para empacotar a interface solicitada de forma transparente de volta para o cliente, que nesse caso é o SQL Server. Esse executável pode aceitar várias solicitações de interface/método simultaneamente. Após a conclusão do uso da interface, o SCM (Gerenciador de Controle de Serviço) do DCOM gerencia a limpeza e o descarregamento do arquivo dllhost.exe . Não se deve esperar que objetos COM mantenham informações de estado entre instanciações.

As etapas a seguir podem ser aplicadas a qualquer objeto COM baseado em DLL que esteja sendo criado no espaço de processo SQL Server, seja ele instanciado por meio sp_OACreate ou por um procedimento armazenado estendido.

Mais informações

As informações sobre os dois métodos básicos que você pode usar para instanciar o objeto COM fora do processo seguem.

Solicitações de cliente COM remoção do objeto

Alterando a maneira como você invoca o objeto COM, você pode solicitar que o objeto seja criado fora do espaço de endereço SQL Server.

  • Se o objeto COM for carregado usando o sp_OACreate procedimento, por padrão, ele será carregado em processo. No entanto, há um terceiro parâmetro opcional para este procedimento que pode ser usado para indicar o contexto de onde criar o objeto. Se esse parâmetro não for especificado, a configuração padrão de cinco (5) será usada, o que significa executar o objeto dentro ou fora do processo. Você precisa alterar o parâmetro para quatro (4), o que indica ao DCOM que esse componente deve ser executado como um executável local. Use a sintaxe semelhante ao exemplo a seguir para informar explicitamente o DCOM para executar o objeto COM fora do processo usando o sp_OACreate procedimento armazenado:

    DECLARE @object int
    DECLARE @hr int
    EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
    
  • Se o objeto COM for criado em um procedimento armazenado estendido, o terceiro parâmetro de CoCreateInstance ou CoCreateInstanceEx poderá ser alterado para CLSCTX_LOCAL_SERVER. Isso é mostrado no exemplo de código a seguir usando CoCreateInstance:

    HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER,
    IID_IUnknown, (void**)&piunknown);
    

Modificar o registro para forçar a remoção do objeto

Se você não puder modificar o cliente COM para solicitar que o objeto seja criado fora do processo, existem dois métodos diferentes para forçar a criação do objeto fora do processo.

  • Use o visualizador de objeto OLE/COM (oleview.exe) que é enviado com o Visual C++ e localize o ProgID na forma de OLEComponent.Object em Todos os Objetos. Selecione o objeto COM e, em seguida, no menu Objeto , selecione CoCreateInstance Sinalizadores. Verifique se isso só CLSCTX_LOCAL_SERVER está selecionado. Em seguida, nas guias Implementação e Servidor Inproc , selecione Usar Processo Substituto e deixe o Caminho para Substituto Personalizado em branco, o que permite que o arquivo dllhost.exe seja carregado e a DLL COM seja trazida em seu espaço de processo.

  • Use as etapas a seguir para atualizar manualmente o registro.

    Aviso

    Poderão ocorrer sérios problemas se você modificar o Registro incorretamente com o Editor do Registro ou outro método. Esses problemas podem exigir a reinstalação do sistema operacional. A Microsoft não garante que esses problemas possam ser solucionados. Modifique o Registro a seu próprio risco.

    1. Obtenha o CLSID (Identificador de Classe) do objeto COM. O CLSID é um número de 128 bits e considerado um GUID (Identificador Globalmente Exclusivo) que é usado para identificar exclusivamente o componente, o módulo ou o arquivo que contém esse objeto COM. Ao criar objetos COM usando os procedimentos armazenados da Automação OLE, o primeiro parâmetro para o procedimento armazenado é um identificador programático ou o ProgID do objeto OLE é usado para derivar o CLSID. Esta cadeia de caracteres descreve a classe do objeto OLE e tem o seguinte formulário:

      OLEComponent.Object
      
    2. Você pode usar o identificador programático para localizar o identificador de classe de um objeto COM.

      Abra a Editor do Registro (regedit.exe) e, na HKEY_CLASSES_ROOT chave, use o Find método para localizar uma chave com o nome do <objeto OLEComponent.>. Você o encontrará em outros níveis, mas ele deve estar localizado no nível diretamente abaixo do HKEY_CLASSES_ROOT. Depois de localizar a chave, expanda a pasta para o nome da chave e verá uma subchave chamada CLSID. Selecione essa pasta para ver os valores dentro dessa chave. No lado direito da tela está um título chamado Default. Os dados dessa chave devem estar no seguinte formulário:

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

      Anote esse valor ou copie-o para o Bloco de Notas. Inclua os colchetes.

    3. Navegue sob a HKEY_CLASSES_ROOT\CLSID chave e localize a subchave com esse número GUID. Depois de realçar a HKEY_CLASSES_ROOT\CLSID chave, você pode usar a função Localizar no Registro Editor (no menu Editar) e colar o GUID na caixa de diálogo Localizar. Verifique se você encontrou a interface adequada inspecionando a subchave InprocServer32 sob essa chave, que aponta para o local do arquivo DLL COM. Se houver uma chave TypeLib, marcar esse valor GUID. Isso deve ser diferente do que você observou na etapa 1. Caso contrário, você tem o GUID TypeLib e não o GUID para o objeto COM. A subchave ProgID terá um valor de OLEComponent.Object.1. O no final é somente para este exemplo e é usado para informações de versão.

    4. Enquanto estiver na subchave InprocServer32 do GUID, verifique se existe um ThreadingModel valor e se ele está definido como Ambos ou Livre para garantir que o marshaling entenda o modelo de threading do objeto COM para habilitar a execução do COM fora do SQL Server espaço de processo. Se não houver um ThreadingModel valor ou estiver definido como Apartment, a instanciação de objeto COM pode não ser consistente.

      Observação

      Se você adicionar o ThreadingModel valor, verifique se você testa seu objeto COM antes de implementar.

    5. Realçar o número/subchave GUID na HKEY_CLASSES_ROOT\CLSID chave. No menu Editar , selecione Novo e, em seguida, selecione Valor de Cadeia de Caracteres. Na coluna Nome , digite AppID.

    6. Pressione ENTER e insira o identificador de classe ou o número GUID que você observou da etapa 1 como o valor. O GUID deve estar dentro dos colchetes encaracolados como no exemplo a seguir:

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

      O AppID do identificador de aplicativo é usado pelo DCOM para associar a DLL a um arquivo executável.

    7. Adicione uma nova subchave no HKEY_CLASSES_ROOT\AppID e defina seu nome como o mesmo identificador de classe ou número GUID com os colchetes inseridos na etapa anterior.

    8. Realçar o nome GUID. No menu Editar , selecione Novo e, em seguida, selecione Valor de Cadeia de Caracteres. Na coluna Nome , digite dllSurrogate.

      Deixe a coluna Dados em branco para esse valor. Como a coluna de dados está em branco, isso informa o DCOM para executar o arquivo executável padrão, dllhost.exee carregar o objeto COM em seu espaço de processo.

    9. Feche o Editor do Registro. Clique em Iniciar e, em seguida, selecione Executar. Na caixa de diálogo Executar , digite DCOMCNFG.

      Pressione a tecla ENTER para abrir a caixa de diálogo Propriedades de Configuração COM Distribuídas . Clique na guia Propriedades Padrão e verifique se Habilitar COM Distribuído neste computador está selecionado. Se não for, selecione-o e selecione Aplicar.

    10. Verifique se a Windows NT conta de usuário em que SQL Server está em execução tem permissão de Controle Total nas chaves do registro desse objeto. Se as permissões não forem suficientes ou as chaves do registro forem inseridas incorretamente, os seguintes erros poderão ocorrer quando você estiver criando o objeto COM:

      Informações de erro de automação OLE
      HRESULT: 0x80040154
      Fonte: Procedimento Estendido ODSOLE
      Descrição: Classe não registrada

      Informações de erro de automação OLE
      HRESULT: 0x80070005
      Fonte: Procedimento Estendido ODSOLE
      Descrição: o acesso é negado.

      Informações de erro de automação OLE
      HRESULT: 0x80080005
      Fonte: Procedimento Estendido ODSOLE
      Descrição: falha na execução do servidor

    11. Teste e veja se isso está executando o arquivodllhost.exe e carregando o objeto COM em seu espaço de processo. Isso requer que o kit de recursos Windows NT esteja no Windows NT computador no qual SQL Server está em execução. Abra um prompt de comando e, no prompt de comando, execute o arquivo tlist.exe , que mostra todos os processos e seus identificadores de processo associados ou PIDs (Identificadores de Processo). No script Transact-SQL em sp_OACreate que é executado e depois que essa chamada é executada, mas antes do script terminar, use o seguinte para atrasar a conclusão do script por mais 20 segundos:

      WAITFOR DELAY '000:00:20'
      

      Execute o script e navegue imediatamente até o prompt de comando e execute o arquivo tlist.exe . Observe o PIDdllhost.exe . Execute novamentetlist.exe e passe o PID como um parâmetro. Isso mostra as DLLs carregadas no espaço de processodllhost.exe . O objeto COM baseado em DLL deve ser listado como em execução nesse processo. Após o retorno do script, a execução tlist.exe novamente revela que o processo dedllhost.exe não está mais em execução.

      Na saída de exemplo a seguir, o ADODB. O objeto Connection é criado fora do SQL Server espaço de processo. Esse instantâneo usando tlist.exe foi executado enquanto o objeto COM existia no dllhost.exe espaço de processo. Observe que o módulo msado15.dll, que é o módulo que contém o objeto COM, é carregado.

      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
      

Referências

Procedimentos armazenados de automação OLE (Transact-SQL)