Mengekspos komponen .NET Core ke COM

Artikel ini memancang Anda tentang cara mengekspos kelas ke COM dari .NET Core (atau .NET 5+). Tutorial ini akan menunjukkan cara untuk:

  • Mengekspos kelas ke COM dari .NET Core.
  • Buat server COM sebagai bagian dari membangun pustaka .NET Core Anda.
  • Secara otomatis menghasilkan manifes server berdampingan untuk COM Bebas Registri.

Prasyarat

Membuat pustaka

Langkah pertama adalah membuat pustaka.

  1. Buat folder baru, dan di folder tersebut jalankan perintah berikut:

    dotnet new classlib
    
  2. Buka Class1.cs.

  3. Tambahkan using System.Runtime.InteropServices; ke bagian atas file.

  4. Buat antarmuka bernama IServer. Misalnya:

    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>")] Tambahkan atribut ke antarmuka, dengan GUID antarmuka untuk antarmuka COM yang Anda terapkan. Contohnya, [Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")]. Perhatikan bahwa GUID ini harus unik karena ini adalah satu-satunya pengidentifikasi antarmuka ini untuk COM. Di Visual Studio, Anda dapat membuat GUID dengan membuka Alat > Membuat GUID untuk membuka alat Buat GUID.

  6. [InterfaceType] Tambahkan atribut ke antarmuka dan tentukan antarmuka COM dasar apa yang harus diterapkan antarmuka Anda.

  7. Buat kelas bernama Server yang mengimplementasikan IServer.

  8. [Guid("<CLSID>")] Tambahkan atribut ke kelas , dengan GUID pengidentifikasi kelas untuk kelas COM yang Anda terapkan. Contohnya, [Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")]. Seperti halnya GUID antarmuka, GUID ini harus unik karena ini adalah satu-satunya pengidentifikasi antarmuka ini ke COM.

  9. [ComVisible(true)] Tambahkan atribut ke antarmuka dan kelas .

Penting

Tidak seperti dalam .NET Framework, .NET Core mengharuskan Anda menentukan CLSID dari kelas apa pun yang ingin Anda aktifkan melalui COM.

Hasilkan host COM

  1. .csproj Buka file proyek dan tambahkan <EnableComHosting>true</EnableComHosting> di dalam <PropertyGroup></PropertyGroup> tag.
  2. Bangun proyek.

Output yang dihasilkan akan memiliki ProjectName.dllfile , ProjectName.deps.json, ProjectName.runtimeconfig.json dan ProjectName.comhost.dll .

Mendaftarkan host COM untuk COM

Buka prompt perintah yang ditingkatkan dan jalankan regsvr32 ProjectName.comhost.dll. Itu akan mendaftarkan semua objek .NET anda yang terekspos dengan COM.

Mengaktifkan RegFree COM

  1. .csproj Buka file proyek dan tambahkan <EnableRegFreeCom>true</EnableRegFreeCom> di dalam <PropertyGroup></PropertyGroup> tag.
  2. Bangun proyek.

Output yang dihasilkan sekarang juga akan memiliki ProjectName.X.manifest file. File ini adalah manifes berdampingan untuk digunakan dengan COM Bebas Registri.

Menyematkan pustaka jenis di host COM

Tidak seperti dalam .NET Framework, tidak ada dukungan di .NET Core atau .NET 5+ untuk menghasilkan Com Type Library (TLB) dari rakitan .NET. Panduannya adalah menulis file IDL secara manual atau header C/C++ untuk deklarasi asli antarmuka COM. Jika Anda memutuskan untuk menulis file IDL, Anda dapat mengkompilasinya dengan pengkompilasi MIDL Visual C++ SDK untuk menghasilkan TLB.

Di .NET 6 dan versi yang lebih baru, .NET SDK mendukung penyematan TLB yang sudah dikompilasi ke host COM sebagai bagian dari build proyek Anda.

Untuk menyematkan pustaka jenis ke dalam aplikasi Anda, ikuti langkah-langkah berikut:

  1. .csproj Buka file proyek dan tambahkan <ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" /> di dalam <ItemGroup></ItemGroup> tag.
  2. Ganti <id> dengan nilai bilangan bulat positif. Nilai harus unik di antara TLB yang Anda tentukan untuk disematkan di host COM.
    • Atribut Id bersifat opsional jika Anda hanya menambahkannya ComHostTypeLibrary ke proyek Anda.

Misalnya, blok kode berikut menambahkan Server.tlb pustaka jenis pada indeks 1 ke host COM:

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

Memuat dalam default AssemblyLoadContext

Selama aktivasi, rakitan yang berisi komponen COM dimuat dalam terpisah AssemblyLoadContext berdasarkan jalur perakitan. Jika ada satu perakitan yang menyediakan beberapa server COM, AssemblyLoadContext digunakan kembali sehingga semua server dari rakitan tersebut berada dalam konteks beban yang sama. Jika ada beberapa rakitan yang menyediakan server COM, yang baru AssemblyLoadContext dibuat untuk setiap perakitan, dan setiap server berada dalam konteks beban yang sesuai dengan rakitannya.

Di .NET 8 dan versi yang lebih baru, rakitan dapat menentukan bahwa rakitan harus dimuat dalam default AssemblyLoadContext. Untuk mengaktifkan pemuatan dalam konteks default, tambahkan item RuntimeHostConfigurationOption berikut ke proyek:

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

Sampel

Ada sampel server COM yang berfungsi penuh di repositori dotnet/sampel di GitHub.

Catatan tambahan

Penting

Dalam .NET Framework, rakitan "CPU apa pun" dapat dikonsumsi oleh klien 32-bit dan 64-bit. Secara default, dalam rakitan .NET Core, .NET 5, dan versi yang lebih baru, "CPU Apa pun" disertai dengan *.comhost.dll 64-bit. Karena itu, mereka hanya dapat dikonsumsi oleh klien 64-bit. Itu adalah default karena itulah yang diwakili SDK. Perilaku ini identik dengan bagaimana fitur "mandiri" diterbitkan: secara default menggunakan apa yang disediakan SDK. Properti NETCoreSdkRuntimeIdentifier MSBuild menentukan bitness * .comhost.dll. Bagian terkelola sebenarnya adalah agnostik bitness seperti yang diharapkan, tetapi aset asli yang menyertainya default ke SDK yang ditargetkan.

Penyebaran komponen COM mandiri tidak didukung. Hanya penyebaran komponen COM yang bergantung pada kerangka kerja yang didukung.

Selain itu, memuat .NET Framework dan .NET Core ke dalam proses yang sama memang memiliki batasan diagnostik. Batasan utama adalah penelusuran kesalahan komponen terkelola karena tidak dimungkinkan untuk men-debug .NET Framework dan .NET Core secara bersamaan. Selain itu, dua instans runtime tidak berbagi rakitan terkelola. Ini berarti bahwa tidak mungkin untuk berbagi jenis .NET aktual di dua runtime dan sebaliknya semua interaksi harus dibatasi untuk kontrak antarmuka COM yang terekspos.