Verfügbarmachen von .NET Core-Komponenten in COM

In diesem Artikel erfahren Sie, wie Sie eine Klasse aus .NET Core (oder .NET 5+) für COM verfügbar machen. In diesem Tutorial lernen Sie:

  • Verfügbarmachen einer Klasse für COM in .NET Core
  • Generieren eines COM-Servers bei der Erstellung einer .NET Core-Bibliothek
  • Automatisches Generieren eines Manifests zur parallelen Serverausführung ohne COM-Registrierung

Voraussetzungen

Erstellen der Bibliothek

Im ersten Schritt erstellen Sie die Bibliothek.

  1. Erstellen Sie einen neuen Ordner, und führen Sie in diesem Ordner den folgenden Befehl aus:

    dotnet new classlib
    
  2. Öffnen Sie Class1.cs.

  3. Fügen Sie using System.Runtime.InteropServices; am Anfang der Datei ein.

  4. Erstellen Sie eine Schnittstelle mit dem Namen IServer. Zum Beispiel:

    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. Fügen Sie der Schnittstelle das [Guid("<IID>")]-Attribut mit der Schnittstellen-GUID für die COM-Schnittstelle hinzu, die Sie implementieren. Beispielsweise [Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")]. Diese GUID muss eindeutig sein, da sie der einzige Bezeichner dieser COM-Schnittstelle ist. In Visual Studio können Sie eine GUID generieren, indem Sie „Extras“ > „GUID erstellen“ aufrufen, um das Tool zum Erstellen einer grafischen Benutzeroberfläche zu verwenden.

  6. Fügen Sie der Schnittstelle das [InterfaceType]-Attribut hinzu, und geben Sie an, welche COM-Basisschnittstellen Ihre Schnittstelle implementieren soll.

  7. Erstellen Sie eine Klasse mit dem Namen Server, die IServer implementiert.

  8. Fügen Sie der Klasse das [Guid("<CLSID>")]-Attribut mit der Klassenbezeichner-GUID für die COM-Klasse hinzu, die Sie implementieren. Beispielsweise [Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")]. Diese GUID muss genau wie die Schnittstellen-GUID eindeutig sein, da sie der einzige Bezeichner dieser COM-Schnittstelle ist.

  9. Fügen Sie der Schnittstelle und der Klasse das [ComVisible(true)]-Attribut hinzu.

Wichtig

Anders als im .NET Framework müssen Sie in .NET Core die CLSID jeder Klasse angeben, die über COM aktivierbar sein soll.

Generieren des COM-Hosts

  1. Öffnen Sie die Projektdatei .csproj, und fügen Sie <EnableComHosting>true</EnableComHosting> innerhalb eines <PropertyGroup></PropertyGroup>-Tags hinzu.
  2. Erstellen Sie das Projekt.

Die Ausgabe enthält die Dateien ProjectName.dll, ProjectName.deps.json, ProjectName.runtimeconfig.json und ProjectName.comhost.dll.

Registrieren des COM-Hosts für COM

Öffnen Sie eine Eingabeaufforderung mit erhöhten Rechten, und führen Sie regsvr32 ProjectName.comhost.dll aus. Dadurch werden alle verfügbaren .NET-Objekte bei COM registriert.

Aktivieren von COM ohne Registrierung

  1. Öffnen Sie die Projektdatei .csproj, und fügen Sie <EnableRegFreeCom>true</EnableRegFreeCom> innerhalb eines <PropertyGroup></PropertyGroup>-Tags hinzu.
  2. Erstellen Sie das Projekt.

Die Ausgabe enthält nun auch die Datei ProjectName.X.manifest. Bei dieser Datei handelt es sich um das Manifest zur parallelen Ausführung, das ohne COM-Registrierung verwendet werden kann.

Einbetten von Typbibliotheken im COM-Host

Anders als im .NET Framework wird in .NET Core oder .NET 5 und höher die Erstellung einer COM-Typbibliothek (TLB) aus einer .NET-Assembly nicht unterstützt. Die Anweisung besagt, dass Sie manuell eine IDL-Datei oder einen C++ Header für die nativen Deklarationen Ihrer Schnittstellen schreiben müssen. Wenn Sie eine IDL-Datei schreiben möchten, können Sie sie mit dem MIDL-Compiler des Visual C++ SDK kompilieren, um einen TLB zu erstellen.

In .NET 6 oder höher unterstützt das .NET SDK das Einbetten bereits kompilierter TLBs in den COM-Host als Teil Ihres Projektbuilds.

Führen Sie die folgenden Schritte aus, um eine Typbibliothek in Ihre Anwendung einzubetten:

  1. Öffnen Sie die Projektdatei .csproj, und fügen Sie <ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" /> in ein <ItemGroup></ItemGroup>-Tag ein.
  2. Ersetzen Sie <id> durch eine positive ganze Zahl. Der Wert muss in den TLBs eindeutig sein, die Sie angeben, um in den COM-Host eingebettet zu werden.
    • Das Id-Attribut ist optional, wenn Sie ihrem Projekt nur ein ComHostTypeLibrary-Attribut hinzufügen.

Der folgende Codeblock fügt dem COM-Host beispielsweise die Server.tlb-Typbibliothek bei Index 1 hinzu:

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

Laden in der AssemblyLoadContext-Standardklasse

Während der Aktivierung wird die Assembly, die die COM-Komponente enthält, auf Basis des Assemblypfads in einer separaten AssemblyLoadContext-Klasse geladen. Wenn eine Assembly mehrere COM-Server bereitstellt, wird AssemblyLoadContext wiederverwendet, sodass sich alle Server aus dieser Assembly im gleichen Ladekontext befinden. Wenn mehrere Assemblys COM-Server bereitstellen, wird für jede Assembly ein neues AssemblyLoadContext-Objekt erstellt, und jeder Server befindet sich im Ladekontext, der seiner Assembly entspricht.

In .NET 8 und höheren Versionen kann die Assembly angeben, dass sie in der Standardklasse AssemblyLoadContext geladen werden soll. Um das Laden im Standardkontext zu aktivieren, fügen Sie dem Projekt das folgende RuntimeHostConfigurationOption-Element hinzu:

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

Beispiel

Ein voll funktionsfähiges Beispiel für COM-Server finden Sie im GitHub-Repository „dotnet/samples“.

Zusätzliche Hinweise

Wichtig

In .NET Framework kann eine Assembly mit beliebiger CPU sowohl von 32-Bit- als auch von 64-Bit-Clients verwendet werden. In .NET Core, .NET 5 und höheren Versionen umfassen Assemblys mit beliebiger CPU standardmäßig eine *.comhost.dll-64-Bit-Datei. Aus diesem Grund können sie nur von 64-Bit-Clients verwendet werden. Dabei handelt es sich aufgrund des SDK um den Standard. Dieses Verhalten ist mit der Veröffentlichung des Unabhängigkeitsfeatures identisch: es werden standardmäßig die vom SDK bereitgestellten Komponenten verwendet. Die MSBuild-Eigenschaft NETCoreSdkRuntimeIdentifier bestimmt die Bitanzahl von *.comhost.dll. Der verwaltete Teil ist erwartungsgemäß tatsächlich unabhängig von der Bitanzahl, jedoch verwendet das zugehörige native Asset standardmäßig das Ziel-SDK.

Eigenständige Bereitstellungen von COM-Komponenten werden nicht unterstützt. Nur frameworkabhängige Bereitstellungen von COM-Komponenten werden unterstützt.

Zusätzlich gelten für das Laden von .NET Framework und .NET Core in denselben Prozess Diagnoseeinschränkungen. Die erste Einschränkung ist das Debuggen von verwalteten Komponenten, da es nicht möglich ist, .NET Framework und .NET Core gleichzeitig zu debuggen. Zusätzlich teilen die beiden Runtimeinstanzen keine verwalteten Assemblys. Das bedeutet, dass es nicht möglich ist, die tatsächlichen .NET-Typen über zwei Runtimes freizugeben. Stattdessen unterliegen alle Interaktionen den verfügbar gemachten Verträgen zur COM-Schnittstelle.