Dela via


Exponera .NET Core-komponenter för COM

Den här artikeln beskriver hur du exponerar en klass för COM från .NET Core (eller .NET 5+). I den här självstudiekursen lär du dig att:

  • Exponera en klass för COM från .NET Core.
  • Generera en COM-server som en del av att skapa .NET Core-biblioteket.
  • Generera automatiskt ett servermanifest sida vid sida för registerfri COM.

Förutsättningar

Skapa biblioteket

Det första steget är att skapa biblioteket.

  1. Skapa en ny mapp och kör följande kommando i mappen:

    dotnet new classlib
    
  2. Öppna Class1.cs.

  3. Lägg till using System.Runtime.InteropServices; längst upp i filen.

  4. Skapa ett gränssnitt med namnet IServer. Till exempel:

    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. [Guid("<IID>")] Lägg till attributet i gränssnittet med gränssnittets GUID för DET COM-gränssnitt som du implementerar. Exempel: [Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")] Observera att detta GUID måste vara unikt eftersom det är den enda identifieraren för det här gränssnittet för COM. I Visual Studio kan du generera ett GUID genom att gå till Verktyg > Skapa GUID för att öppna verktyget Skapa GUID.

  6. [InterfaceType] Lägg till attributet i gränssnittet och ange vilka grundläggande COM-gränssnitt som gränssnittet ska implementera.

  7. Skapa en klass med namnet Server som implementerar IServer.

  8. [Guid("<CLSID>")] Lägg till attributet i klassen med klassidentifieraren GUID för DEN COM-klass som du implementerar. Exempel: [Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")] Precis som med gränssnittets GUID måste detta GUID vara unikt eftersom det är den enda identifieraren för det här gränssnittet för COM.

  9. [ComVisible(true)] Lägg till attributet i både gränssnittet och klassen.

Viktigt!

Till skillnad från i .NET Framework kräver .NET Core att du anger CLSID för alla klasser som du vill ska kunna aktiveras via COM.

Generera COM-värden

  1. .csproj Öppna projektfilen och lägg till <EnableComHosting>true</EnableComHosting> i en <PropertyGroup></PropertyGroup> tagg.
  2. Bygga projektet.

De resulterande utdata kommer att ha en ProjectName.dll, ProjectName.deps.jsonProjectName.runtimeconfig.json och ProjectName.comhost.dll -fil.

Registrera COM-värden för COM

Öppna en upphöjd kommandotolk och kör regsvr32 ProjectName.comhost.dll. Då registreras alla dina exponerade .NET-objekt med COM.

Om du tänker bädda in ett typbibliotek (TLB) rekommenderar vi att du även definierar funktioner med hjälp av ComRegisterFunctionAttribute och ComUnregisterFunctionAttribute. Dessa funktioner kan användas för att registrera och avregistrera TLB för COM-servern. Ett fullständigt exempel finns i exemplet OutOfProcCOM .

Aktivera RegFree COM

  1. .csproj Öppna projektfilen och lägg till <EnableRegFreeCom>true</EnableRegFreeCom> i en <PropertyGroup></PropertyGroup> tagg.
  2. Bygga projektet.

De resulterande utdata kommer nu också att ha en ProjectName.X.manifest fil. Den här filen är manifestet sida vid sida för användning med Registerfri COM.

Inbäddningstypbibliotek i COM-värden

Till skillnad från i .NET Framework finns det inget stöd i .NET Core eller .NET 5+ för att generera ett COM-typbibliotek (TLB) från en .NET-sammansättning. Vägledningen är att antingen manuellt skriva en IDL-fil eller ett C/C++-huvud för de interna deklarationerna i COM-gränssnitten. Om du bestämmer dig för att skriva en IDL-fil kan du kompilera den med Visual C++ SDK:s MIDL-kompilator för att skapa en TLB.

I .NET 6 och senare versioner stöder .NET SDK inbäddning av redan kompilerade TLB:er i COM-värden som en del av projektversionen.

Följ dessa steg för att bädda in ett typbibliotek i ditt program:

  1. .csproj Öppna projektfilen och lägg till <ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" /> i en <ItemGroup></ItemGroup> tagg.
  2. Ersätt <id> med ett positivt heltalsvärde. Värdet måste vara unikt bland de TLB:er som du anger för att bäddas in i COM-värden.
    • Attributet Id är valfritt om du bara lägger till ett ComHostTypeLibrary i projektet.

Följande kodblock lägger Server.tlb till exempel typbiblioteket i index 1 till COM-värden:

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

Läser in i standardinställningen AssemblyLoadContext

Under aktiveringen läses sammansättningen som innehåller COM-komponenten in i en separat AssemblyLoadContext baserat på sammansättningssökvägen. Om det finns en sammansättning som tillhandahåller flera COM-servrar AssemblyLoadContext återanvänds den så att alla servrar från den sammansättningen finns i samma belastningskontext. Om det finns flera sammansättningar som tillhandahåller COM-servrar skapas en ny AssemblyLoadContext för varje sammansättning och varje server finns i den belastningskontext som motsvarar dess sammansättning.

I .NET 8 och senare versioner kan sammansättningen ange att den ska läsas in i standardversionen AssemblyLoadContext. Om du vill aktivera inläsning i standardkontexten lägger du till följande RuntimeHostConfigurationOption-objekt i projektet:

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

Exempel

Det finns ett fullt fungerande COM-serverexempel på dotnet/samples-lagringsplatsen på GitHub.

Ytterligare kommentarer

Viktigt!

I .NET Framework kan en "Valfri CPU"-sammansättning användas av både 32-bitars- och 64-bitarsklienter. I .NET Core, .NET 5 och senare versioner åtföljs som standard "Alla CPU"-sammansättningar av en 64-bitars *.comhost.dll. Därför kan de bara användas av 64-bitarsklienter. Det är standard eftersom det är vad SDK:et representerar. Det här beteendet är identiskt med hur funktionen "fristående" publiceras: som standard används det som SDK tillhandahåller. Egenskapen NETCoreSdkRuntimeIdentifier MSBuild avgör bitnessen för *.comhost.dll. Den hanterade delen är faktiskt bitness-agnostisk som förväntat, men den medföljande interna tillgången är standard för mål-SDK:t.

Fristående distributioner av COM-komponenter stöds inte. Endast ramverksberoende distributioner av COM-komponenter stöds.

Det går inte att exponera COM-komponenter från C++/CLI-projekt via egenskapen EnableComHosting.

Dessutom har inläsning av både .NET Framework och .NET Core i samma process diagnostiska begränsningar. Den primära begränsningen är felsökning av hanterade komponenter eftersom det inte går att felsöka både .NET Framework och .NET Core samtidigt. Dessutom delar de två körningsinstanserna inte hanterade sammansättningar. Det innebär att det inte går att dela faktiska .NET-typer över de två körningarna och i stället måste alla interaktioner begränsas till de exponerade COM-gränssnittskontrakten.