Esporre componenti di .NET Core a COM

Questo articolo illustra come esporre una classe a COM da .NET Core (o .NET 5+). Questa esercitazione illustra come:

  • Esporre una classe a COM da .NET Core.
  • Generare un server COM nell'ambito della creazione della libreria .NET Core.
  • Generare automaticamente un manifesto del server affiancato per COM senza Registro di sistema.

Prerequisiti

Creare la libreria

Il primo passaggio consiste nel creare la libreria.

  1. Crea una nuova cartella e in tale cartella esegui il comando seguente:

    dotnet new classlib
    
  2. Class1.cs aperti.

  3. Aggiungere using System.Runtime.InteropServices; all'inizio del file.

  4. Creare un'interfaccia denominata IServer. Ad esempio:

    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. Aggiungere l'attributo [Guid("<IID>")] all'interfaccia con il GUID di interfaccia per l'interfaccia COM che si sta implementando. Ad esempio: [Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")]. Si noti che questo GUID deve essere univoco perché è l'unico identificatore di questa interfaccia per COM. In Visual Studio puoi generare un GUID passando a Strumenti > Crea GUID per aprire lo strumento Crea GUID.

  6. Aggiungere l'attributo [InterfaceType] all'interfaccia e specificare le interfacce COM di base che l'interfaccia deve implementare.

  7. Creare una classe denominata Server che implementi IServer.

  8. Aggiungere l'attributo [Guid("<CLSID>")] alla classe con il GUID dell'identificatore di classe per la classe COM che si sta implementando. Ad esempio: [Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")]. Come per il GUID dell'interfaccia, questo GUID deve essere univoco perché è l'unico identificatore di questa interfaccia per COM.

  9. Aggiungere l'attributo [ComVisible(true)] sia all'interfaccia che alla classe.

Importante

Diversamente da quanto avviene in .NET Framework, .NET Core richiede di specificare il CLSID di qualsiasi classe che si vuole rendere attivabile tramite COM.

Generare l'host COM

  1. Aprire il file di progetto .csproj e aggiungere <EnableComHosting>true</EnableComHosting> all'interno di un tag <PropertyGroup></PropertyGroup>.
  2. Compilare il progetto.

L'output risultante includerà un file ProjectName.dll, ProjectName.deps.json, ProjectName.runtimeconfig.json e ProjectName.comhost.dll.

Registrare l'host COM per COM

Aprire un prompt dei comandi con privilegi elevati ed eseguire regsvr32 ProjectName.comhost.dll. Tutti gli oggetti .NET esposti verranno così registrati in COM.

Se si intende incorporare una libreria dei tipi (TLB), è consigliabile definire anche le funzioni usando ComRegisterFunctionAttribute e ComUnregisterFunctionAttribute. Queste funzioni possono essere usate per registrare e annullare la registrazione della libreria dei tipi per il server COM. Per un esempio completo, vedere l'esempio di il campione OutOfProcCOM.

Abilitazione di COM RegFree

  1. Aprire il file di progetto .csproj e aggiungere <EnableRegFreeCom>true</EnableRegFreeCom> all'interno di un tag <PropertyGroup></PropertyGroup>.
  2. Compilare il progetto.

L'output risultante includerà ora anche un file ProjectName.X.manifest. Questo file è il manifesto affiancato da usare con COM senza Registro di sistema.

Incorporamento di librerie dei tipi nell'host COM

Diversamente da .NET Framework, in .NET Core o .NET 5+ non è disponibile alcun supporto per la generazione di una libreria dei tipi COM (TLB) da un assembly .NET. Le indicazioni sono di scrivere manualmente un file IDL o un'intestazione C/C++ per le dichiarazioni native delle interfacce COM. Se decidi di scrivere un file IDL, puoi compilarlo con il compilatore MIDL di Visual C++ SDK per produrre una TLB.

In .NET 6 e versioni successive, .NET SDK supporta l'incorporamento di TLB già compilati nell'host COM come parte della compilazione del progetto.

Per incorporare una libreria dei tipi nell'applicazione, segui questa procedura:

  1. Apri il file di progetto .csproj e aggiungi <ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" /> all'interno di un tag <ItemGroup></ItemGroup>.
  2. Sostituisci <id> con un valore intero positivo. Il valore deve essere univoco tra le TLB specificate per essere incorporato nell'host COM.
    • L'attributo Id è facoltativo se aggiungi un solo ComHostTypeLibrary al progetto.

Ad esempio, il blocco di codice seguente aggiunge la libreria dei tipi Server.tlb in corrispondenza dell'indice 1 all'host COM:

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

Caricamento nel AssemblyLoadContext predefinito

Durante l'attivazione, l'assembly contenente il componente COM viene caricato in un AssemblyLoadContext separato in base al percorso dell'assembly. Se è presente un assembly che fornisce più server COM, AssemblyLoadContext viene riutilizzato in modo che tutti i server di tale assembly si trovino nello stesso contesto di caricamento. Se sono presenti più assembly che forniscono server COM, viene creato un nuovo AssemblyLoadContext per ogni assembly e ogni server risiede nel contesto di caricamento corrispondente al relativo assembly.

In .NET 8 e versioni successive, l'assembly può specificare che deve essere caricato nel AssemblyLoadContext predefinito. Per abilitare il caricamento nel contesto predefinito, aggiungi il seguente elemento RuntimeHostConfigurationOption al progetto:

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.COM.LoadComponentInDefaultContext" Value="true" />
</ItemGroup>

Esempio

È disponibile un esempio di server COM funzionante nel repository dotnet/samples in GitHub.

Note aggiuntive

Importante

In .NET Framework un assembly "Any CPU" può essere utilizzato sia dai client a 32 bit che da quelli 64 bit. Per impostazione predefinita, in .NET Core, .NET 5 e versioni successive gli assembly "Any CPU" sono accompagnati da un *.comhost.dll a 64 bit. Per questo motivo, possono essere utilizzati solo dai client a 64 bit. Questo è il valore predefinito perché è ciò che l'SDK rappresenta. Questo comportamento è identico al modo in cui viene pubblicata la funzionalità "autonoma": per impostazione predefinita usa ciò che fornisce l'SDK. La proprietà MSBuild NETCoreSdkRuntimeIdentifier determina il numero di bit di *.comhost.dll. La parte gestita è in realtà indipendente dal numero di bit come previsto, ma per impostazione predefinita l'asset nativo associato è l'SDK di destinazione.

Le distribuzioni autonome dei componenti COM non sono supportate. Sono supportate solo le distribuzioni dipendenti dal framework dei componenti COM.

L'esposizione di componenti COM da progetti C++/CLI tramite la proprietà EnableComHosting non è supportata.

Inoltre, il caricamento di .NET Framework e .NET Core nello stesso processo presenta limitazioni di diagnostica. La limitazione principale è il debug dei componenti gestiti perché non è possibile eseguire il debug di .NET Framework e .NET Core contemporaneamente. Inoltre, le due istanze di runtime non condividono assembly gestiti. Questo significa che non è possibile condividere i tipi .NET effettivi tra i due runtime e tutte le interazioni devono invece essere limitate ai contratti di interfaccia COM esposti.