Expor componentes do .NET Core ao COM
Este artigo explica como expor uma classe ao COM do .NET Core (ou .NET 5+). Este tutorial mostra como:
- Expor uma classe ao COM do .NET Core.
- Gerar um servidor COM como parte de criar sua biblioteca do .NET Core.
- Gerar automaticamente um manifesto de servidor lado a lado para COM Sem Registro.
Pré-requisitos
- Instale o SDK do .NET Core 3.0 ou uma versão mais recente.
Criar a biblioteca
A primeira etapa é criar a biblioteca.
Crie uma pasta e nela execute o seguinte comando:
dotnet new classlib
Abra o
Class1.cs
.Adicione
using System.Runtime.InteropServices;
ao topo do arquivo.Crie uma interface chamada
IServer
. Por exemplo:using System; using System.Runtime.InteropServices; [ComVisible(true)] [Guid(ContractGuids.ServerInterface)] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IServer { /// <summary> /// Compute the value of the constant Pi. /// </summary> double ComputePi(); }
Adicione o atributo
[Guid("<IID>")]
à interface, com o GUID da interface COM que você está implementando. Por exemplo,[Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")]
. Observe que esse GUID precisa ser exclusivo, pois é o único identificador dessa interface para COM. No Visual Studio, você pode gerar um GUID acessando Ferramentas > Criar GUID para abrir a ferramenta Criar GUID.Adicione o atributo
[InterfaceType]
à interface e especifique quais interfaces COM base sua interface deve implementar.Crie uma classe chamada
Server
que implementaIServer
.Adicione o atributo
[Guid("<CLSID>")]
à classe, com o GUID do identificador de classe da classe COM que você está implementando. Por exemplo,[Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")]
. Como ocorre com o GUID da interface, esse GUID deve ser exclusivo pois é o único identificador dessa interface para COM.Adicione o atributo
[ComVisible(true)]
à interface e à classe.
Importante
Diferentemente do .NET Framework, o .NET Core exige que você especifique o CLSID de qualquer classe que você deseja que seja ativável por meio do COM.
Gerar o host COM
- Abra o arquivo de projeto
.csproj
e adicione<EnableComHosting>true</EnableComHosting>
dentro de uma marca<PropertyGroup></PropertyGroup>
. - Compile o projeto.
A saída resultante terá um arquivo ProjectName.dll
, ProjectName.deps.json
, ProjectName.runtimeconfig.json
e ProjectName.comhost.dll
.
Registrar o host COM para COM
Abra um prompt de comandos com privilégios elevados e execute regsvr32 ProjectName.comhost.dll
. Isso registrará todos os seus objetos .NET expostos com o COM.
Se você pretende incorporar uma biblioteca de tipos (TLB), é recomendado também definir funções usando ComRegisterFunctionAttribute
e ComUnregisterFunctionAttribute
. Essas funções podem ser usadas para registrar e cancelar o registro do TLB para o servidor COM. Para obter um exemplo completo, veja o exemplo OutOfProcCOM
.
Habilitar o COM RegFree
- Abra o arquivo de projeto
.csproj
e adicione<EnableRegFreeCom>true</EnableRegFreeCom>
dentro de uma marca<PropertyGroup></PropertyGroup>
. - Compile o projeto.
A saída resultante agora também terá um arquivo ProjectName.X.manifest
. Esse arquivo é o manifesto lado a lado para uso com o COM Sem Registro.
Inserindo bibliotecas de tipos no host COM
Ao contrário do .NET Framework, não há suporte no .NET Core ou no .NET 5+ para gerar uma TLB (Biblioteca de Tipos) COM por meio de um assembly do .NET. A orientação é escrever manualmente um arquivo IDL ou um cabeçalho C/C++ para as declarações nativas das interfaces COM. Se você decidir escrever um arquivo IDL, poderá compilá-lo com o compilador MIDL do SDK do Visual C++ para produzir uma TLB.
No .NET 6 e em versões posteriores, o SDK do .NET dá suporte à inserção de TLBs já compiladas no host COM como parte da compilação do projeto.
Para inserir uma biblioteca de tipos em seu aplicativo, siga estas etapas:
- Abra o arquivo de projeto
.csproj
e adicione<ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" />
dentro de uma marca<ItemGroup></ItemGroup>
. - Substitua
<id>
por um valor inteiro positivo. O valor deve ser exclusivo entre as TLBs especificadas para sere inserido no host COM.- O atributo
Id
será opcional se você adicionar apenas umComHostTypeLibrary
ao seu projeto.
- O atributo
Por exemplo, o seguinte bloco de código adiciona a biblioteca de tipos Server.tlb
do índice 1
ao host COM:
<ItemGroup>
<ComHostTypeLibrary Include="Server.tlb" Id="1" />
</ItemGroup>
Carregar no AssemblyLoadContext
padrão
Durante a ativação, o assembly que contém o componente COM é carregado em um AssemblyLoadContext separado com base no caminho do assembly. Se houver um assembly que forneça vários servidores COM, AssemblyLoadContext
será reutilizado de modo que todos os servidores desse assembly residam no mesmo contexto de carga. Se houver vários assemblies fornecendo servidores COM, um novo AssemblyLoadContext
será criado para cada assembly e cada servidor residirá no contexto de carga que corresponde ao assembly dele.
No .NET 8 e versões posteriores, o assembly pode especificar que ele deve ser carregado no AssemblyLoadContext
padrão. Para habilitar o carregamento no contexto padrão, adicione o seguinte item RuntimeHostConfigurationOption ao projeto:
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.COM.LoadComponentInDefaultContext" Value="true" />
</ItemGroup>
Amostra
Há um exemplo de servidor COM totalmente funcional no repositório dotnet/de exemplos no GitHub.
Observações adicionais
Importante
Em .NET Framework, um assembly "Any CPU" pode ser consumido por clientes de 32 bits e de 64 bits. Por padrão, no .NET Core, no .NET 5 e em versões posteriores, os assemblies "Any CPU" são acompanhados por uma *.comhost.dll de 64 bits. Por isso, eles só podem ser consumidos por clientes de 64 bits. Esse é o padrão porque é isso que o SDK representa. Esse comportamento é idêntico à forma como o recurso "autossuficiente" é publicado: por padrão, ele usa o que o SDK fornece. A propriedade MSBuild de NETCoreSdkRuntimeIdentifier
determina o número de bit da *.comhost.dll. A parte gerenciada é realmente agnóstica do número de bit, conforme o esperado, mas o ativo nativo que a acompanha assume como padrão o SDK de destino.
Não há suporte para implantações autossuficientes de componentes COM. Há suporte apenas para as implantações dependentes de estrutura de componentes COM.
Não há suporte para a exposição de componentes COM de projetos C++/CLI por meio da propriedade EnableComHosting.
Além disso, carregar .NET Framework e .NET Core no mesmo processo tem limitações de diagnóstico. A principal limitação é a depuração de componentes gerenciados, pois não é possível depurar o .NET Framework e o .NET Core ao mesmo tempo. Além disso, as duas instâncias de runtime não compartilham assemblies gerenciados. Isso significa que não é possível compartilhar tipos reais do .NET entre os dois runtimes e, em vez disso, todas as interações devem ser restritas aos contratos de interface COM expostos.