Partilhar via


Expor componentes do .NET Core ao COM

Este artigo orienta você sobre como expor uma classe para COM do .NET Core (ou .NET 5+). Este tutorial mostrar-lhe como:

  • Exponha uma classe para COM do .NET Core.
  • Gere um servidor COM como parte da criação de sua biblioteca .NET Core.
  • Gere automaticamente um manifesto do servidor lado a lado para COM sem registro.

Pré-requisitos

Criar a biblioteca

O primeiro passo é criar a biblioteca.

  1. Crie uma nova pasta e, nessa pasta, execute o seguinte comando:

    dotnet new classlib
    
  2. Abrir Class1.cs.

  3. Adicionar using System.Runtime.InteropServices; à parte superior do ficheiro.

  4. 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();
    }
    
  5. Adicione o [Guid("<IID>")] atributo à interface, com o GUID da interface para a 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 indo para Ferramentas > Criar GUID para abrir a ferramenta Criar GUID.

  6. Adicione o [InterfaceType] atributo à interface e especifique quais interfaces COM base sua interface deve implementar.

  7. Crie uma classe chamada Server que implemente IServero .

  8. Adicione o [Guid("<CLSID>")] atributo à classe, com o GUID do identificador de classe para a classe COM que você está implementando. Por exemplo, [Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")]. Tal como acontece com o GUID da interface, este GUID deve ser exclusivo, uma vez que é o único identificador desta interface para COM.

  9. Adicione o [ComVisible(true)] atributo à interface e à classe.

Importante

Ao contrário do .NET Framework, o .NET Core requer que você especifique o CLSID de qualquer classe que você deseja que seja ativável via COM.

Gerar o host COM

  1. Abra o arquivo de .csproj projeto e adicione <EnableComHosting>true</EnableComHosting> dentro de uma <PropertyGroup></PropertyGroup> tag .
  2. Compilar o projeto.

A saída resultante terá um ProjectName.dllarquivo , ProjectName.deps.jsonProjectName.runtimeconfig.json e ProjectName.comhost.dll .

Registrar o host COM para COM

Abra um prompt de comando elevado e execute regsvr32 ProjectName.comhost.dllo . Isso registrará todos os seus objetos .NET expostos com COM.

Se você pretende incorporar uma biblioteca de tipos (TLB), é recomendável 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, consulte o OutOfProcCOM exemplo.

Ativando o RegFree COM

  1. Abra o arquivo de .csproj projeto e adicione <EnableRegFreeCom>true</EnableRegFreeCom> dentro de uma <PropertyGroup></PropertyGroup> tag .
  2. Compilar o projeto.

A saída resultante agora também terá um ProjectName.X.manifest arquivo. Este arquivo é o manifesto lado a lado para uso com COM sem registro.

Incorporando 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 biblioteca de tipos COM (TLB) a partir de um assembly .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, você pode compilá-lo com o compilador MIDL do Visual C++ SDK para produzir um TLB.

No .NET 6 e versões posteriores, o SDK do .NET oferece suporte à incorporação de TLBs já compilados no host COM como parte da compilação do projeto.

Para incorporar uma biblioteca de tipos em seu aplicativo, execute estas etapas:

  1. Abra o arquivo de .csproj projeto e adicione <ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" /> dentro de uma <ItemGroup></ItemGroup> tag .
  2. Substitua <id> por um valor inteiro positivo. O valor deve ser exclusivo entre os TLBs especificados para serem incorporados no host COM.
    • O Id atributo é opcional se você adicionar apenas um ComHostTypeLibrary ao seu projeto.

Por exemplo, o bloco de código a seguir adiciona a biblioteca de Server.tlb tipos no índice 1 ao host COM:

<ItemGroup>
    <ComHostTypeLibrary Include="Server.tlb" Id="1" />
</ItemGroup>

Carregando no padrão AssemblyLoadContext

Durante a ativação, o assembly que contém o componente COM é carregado em um separado AssemblyLoadContext com base no caminho de montagem. Se houver um assembly fornecendo vários servidores COM, o 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 seu assembly.

No .NET 8 e versões posteriores, o assembly pode especificar que ele deve ser carregado no padrão AssemblyLoadContext. 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>

Exemplo

Há um exemplo de servidor COM totalmente funcional no repositório dotnet/samples no GitHub.

Notas adicionais

Importante

No .NET Framework, um assembly "Qualquer CPU" pode ser consumido por clientes de 32 bits e 64 bits. Por padrão, no .NET Core, .NET 5 e versões posteriores, os assemblies "Qualquer CPU" são acompanhados por um *.comhost.dll de 64 bits. Por causa disso, 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 "autônomo" é publicado: por padrão, ele usa o que o SDK fornece. A NETCoreSdkRuntimeIdentifier propriedade MSBuild determina o número de bits de *.comhost.dll. A parte gerenciada é, na verdade, agnóstica de bitness, 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 autônomas de componentes COM. Somente implantações dependentes da estrutura de componentes COM são suportadas.

Além disso, carregar o .NET Framework e o .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 tempo de execução não compartilham assemblies gerenciados. Isso significa que não é possível compartilhar tipos .NET reais entre os dois tempos de execução e, em vez disso, todas as interações devem ser restritas aos contratos de interface COM expostos.