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 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 exemplo de código a seguir usandoCoCreateInstance
: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 , selecioneCoCreateInstance
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.
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
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 oFind
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 doHKEY_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.
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 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 deOLEComponent.Object.1
. O no final é somente para este exemplo e é usado para informações 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 SQL Server espaço de processo. Se não houver umThreadingModel
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.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.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.
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.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.
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.
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 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
HRESULT: 0x80080005
Fonte: Procedimento Estendido ODSOLE
Descrição: falha na execução do servidorTeste 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
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários