Compartilhar via


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

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

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

Resumo

O Microsoft SQL Server fornece a capacidade de carregar e executar objetos COM (Component Object Model) personalizados por meio de um conjunto de procedimentos armazenados de Automação OLE ou por meio de procedimentos armazenados estendidos. Por padrão, os 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 no espaço de endereço de memória do processo do 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 do SQL Server deve aderir às mesmas regras que qualquer arquivo DLL. Há um potencial de que um objeto COM possa substituir a memória no processo do SQL Server ou vazar recursos, causando instabilidade.

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

O processo de execução de um objeto COM baseado em DLL fora do espaço de endereço do aplicativo principal é chamado de comunicação remota. A comunicação remota requer que outro executável seja um processo substituto no lugar do executável do SQL Server. O executável padrão usado pelo DCOM Service Control Manager (rpcss.exe) é denominado 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 (Service Control Manager) do DCOM gerencia a limpeza e o descarregamento do arquivo dllhost.exe . Não se deve esperar que os objetos COM retenham informações de estado entre as 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 do SQL Server, seja ele instanciado por meio sp_OACreate de um procedimento armazenado estendido ou estendido.

Mais informações

A seguir, são apresentadas informações sobre os dois métodos básicos que você pode usar para instanciar o objeto COM fora do processo.

O cliente COM solicita a comunicação remota 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 do SQL Server.

  • Se o objeto COM for carregado usando o sp_OACreate procedimento, por padrão, ele será carregado no processo. No entanto, há um terceiro parâmetro opcional para esse procedimento que você pode usar 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 uma 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 seguinte exemplo de código usando CoCreateInstance:

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

Modificar o registro para forçar a comunicação remota 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 o objeto a ser criado fora do processo.

  • Use o visualizador de objetos OLE/COM (oleview.exe) fornecido com o Visual C++ e localize o ProgID na forma de OLEComponent.Object em Todos os Objetos. Selecione o objeto COM e, no menu Objeto , selecione CoCreateInstance Sinalizadores. Certifique-se de que apenas CLSCTX_LOCAL_SERVER esteja selecionado. Em seguida, nas guias Implementation e Inproc Server, selecione Use Surrogate Process e deixe o Path to Custom Surrogate em branco, o que permite que o arquivo dllhost.exe seja carregado e a DLL COM seja trazida para dentro de seu espaço de processo.

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

    Aviso

    Poderão ocorrer problemas sérios se você modificar o Registro incorretamente usando 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 Global Exclusivo) usado para identificar exclusivamente o componente, módulo ou 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. Essa cadeia de caracteres descreve a classe do objeto OLE e tem o seguinte formato:

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

      Abra o Editor do Registro (regedit.exe) e, na chave, HKEY_CLASSES_ROOT use o Find método para localizar uma chave com o nome do seu <OLEComponent.Object>. Você o encontrará em outros níveis, mas 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 você verá uma subchave chamada CLSID. Selecione essa pasta para ver os valores dentro dessa chave. No lado direito da tela há um título chamado Default. Os dados dessa chave devem estar no seguinte formato:

      {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 Editor do Registro (no menu Editar ) e colar o GUID na caixa de diálogo Localizar . Verifique se você encontrou a interface adequada inspecionando a subchave InprocServer32 nessa chave, que aponta para o local do arquivo DLL COM. Se houver uma chave TypeLib, verifique esse valor GUID. Isso deve ser diferente do que você observou na etapa 1. Caso contrário, você terá o GUID TypeLib e não o GUID para o objeto COM. A subchave ProgID terá um valor de OLEComponent.Object.1. O que está no final é apenas para este exemplo e é usado para informações de controle 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 espaço de processo do SQL Server. Se não houver um ThreadingModel valor ou ele estiver definido como Apartment, a instanciação do objeto COM poderá não ser consistente.

      Observação

      Se você adicionar o ThreadingModel valor, certifique-se de testar seu objeto COM antes de implementar.

    5. Realce o número/subchave do GUID sob a HKEY_CLASSES_ROOT\CLSID chave. No menu Editar, selecione Novo e, em seguida, selecione Valor da Cadeia de Caracteres. Na coluna Nome, digite AppID.

    6. Pressione ENTER e insira o identificador de classe ou o número GUID que você anotou na etapa 1 como o valor. O GUID deve estar dentro das chaves, como no exemplo a seguir:

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

      O identificador de aplicativo AppID é 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. Realce o nome do GUID. No menu Editar, selecione Novo e, em seguida, selecione Valor da 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 ao DCOM para executar o arquivo executável padrão, dllhost.exe, e carregar o objeto COM em seu espaço de processo.

    9. Feche o Editor do Registro. Clique em Iniciar e 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 do COM Distribuído . Clique na guia Propriedades Padrão e verifique se a opção Habilitar COM Distribuído neste computador está selecionada. Se não estiver, selecione-o e, em seguida, selecione Aplicar.

    10. Verifique se a conta de usuário do Windows NT na qual o SQL Server está sendo executado tem permissão Controle Total nas chaves do Registro para esse objeto. Se as permissões não forem suficientes ou as chaves do Registro forem inseridas incorretamente, os seguintes erros poderão ocorrer ao criar o objeto COM:

      Informações de erro de automação OLE
      RESULTADO: 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
      RESULTADO: 0x80080005
      Fonte: Procedimento Estendido ODSOLE
      Descrição: falha na execução do servidor

    11. Teste e veja se isso está executando o arquivo dllhost.exe e carregando o objeto COM em seu espaço de processo. Isso requer que o Windows NT Resource Kit esteja no computador Windows NT no qual o SQL Server está sendo executado. 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 que sp_OACreate é executado e depois que a chamada é executada, mas antes que o script termine, 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 PID dllhost.exe . Execute novamente tlist.exe e passe o PID como um parâmetro. Isso mostra as DLLs carregadas no espaço de processo dllhost.exe . O objeto COM baseado em DLL deve ser listado como em execução nesse processo. Depois que o script retorna, a execução tlist.exe novamente revela que o processo dllhost.exe não está mais em execução.

      Na saída de exemplo a seguir, o arquivo ADODB. O objeto de conexão é criado fora do espaço de processo do SQL Server. Esse instantâneo usando tlist.exe foi executado enquanto o objeto COM existia no espaço de processo dllhost.exe . 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)