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 osp_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
ouCoCreateInstanceEx
poderá ser alterado paraCLSCTX_LOCAL_SERVER
. Isso é mostrado no seguinte exemplo de código usandoCoCreateInstance
: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 , selecioneCoCreateInstance
Sinalizadores. Certifique-se de que apenasCLSCTX_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.
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
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 oFind
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 doHKEY_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.
Navegue sob a
HKEY_CLASSES_ROOT\CLSID
chave e localize a subchave com esse número GUID. Depois de realçar aHKEY_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 deOLEComponent.Object.1
. O que está no final é apenas para este exemplo e é usado para informações de controle de versão.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 umThreadingModel
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.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.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.
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.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.
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.
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 registradaInformaçõ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 servidorTeste 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