次の方法で共有


COM への .NET Core コンポーネントの公開

この記事では、.NET Core (または .NET 5+) から COM にクラスを公開する方法について説明します。 このチュートリアルでは、次の操作方法について説明します。

  • .NET Core から COM にクラスを公開します。
  • 使用する .NET Core ライブラリをビルドする一環として、COM サーバーを生成します。
  • レジストリを使用しない COM 用の side-by-side サーバー マニフェストを自動生成します。

前提条件

ライブラリを作成する

最初の手順では、ライブラリを作成します。

  1. 新しいフォルダーを作成し、そのフォルダーで次のコマンドを実行します。

    dotnet new classlib
    
  2. Class1.csを開きます。

  3. ファイルの先頭に、using System.Runtime.InteropServices; を追加します。

  4. IServer という名前のインターフェイスを作成します。 次に例を示します。

    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. このインターフェイスに、実装する COM インターフェイス用のインターフェイス GUID を使用して、[Guid("<IID>")] 属性を追加します。 たとえば、[Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")] のようにします。 この GUID は、COM 用のこのインターフェイスの唯一の識別子であるため、一意である必要があることに注意してください。 Visual Studio で GUID を作成するには、[ツール] > [GUID の作成] の順に移動して GUID の作成ツールを開きます。

  6. インターフェイスに [InterfaceType] 属性を追加し、お使いのインターフェイスで実装すべき基本 COM インターフェイスを指定します。

  7. IServer を実装する、Server という名前のクラスを作成します。

  8. クラスに、実装する COM クラス用のクラス識別子 GUID を使用して、[Guid("<CLSID>")] 属性を追加します。 たとえば、[Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")] のようにします。 インターフェイス GUID でこの GUID は、COM ではこのインターフェイスの唯一の識別子であるため、一意である必要があることに注意してください。

  9. インターフェイスとクラスの両方に [ComVisible(true)] 属性を追加します。

重要

.NET Framework とは異なり、.NET Core では COM を使用してアクティブ化したいすべてのクラスの CLSID を指定する必要があります。

COM ホストを生成する

  1. .csproj プロジェクト ファイルを開き、<PropertyGroup></PropertyGroup> タグの内側に <EnableComHosting>true</EnableComHosting> を追加します。
  2. プロジェクトをビルドします。

結果として、ProjectName.dllProjectName.runtimeconfig.jsonProjectName.deps.json、およびProjectName.comhost.dll ファイルが出力されます。

COM 用の COM ホストを登録する

管理者特権でのコマンド プロンプトを開き、regsvr32 ProjectName.comhost.dll を実行します。 これにより、公開されているすべての .NET オブジェクトが COM に登録されます。

Regfree COM を有効にする

  1. .csproj プロジェクト ファイルを開き、<PropertyGroup></PropertyGroup> タグの内側に <EnableRegFreeCom>true</EnableRegFreeCom> を追加します。
  2. プロジェクトをビルドします。

これで結果として、ProjectName.X.manifest ファイルも出力されます。 このファイルが、Registry-Free COM で使用される side-by-side マニフェストです。

COM ホストでのタイプ ライブラリの埋め込み

.NET Framework とは異なり、.NET Core または .NET 5 以降では、.NET アセンブリからの COM タイプ ライブラリ (TLB) の生成はサポートされていません。 このガイダンスは、COM インターフェイスのネイティブ宣言のために、IDL ファイルまたは C/C++ ヘッダーを手動で記述する方法について説明するものです。 IDL ファイルを記述する場合は、Visual C++ SDK の MIDL コンパイラを使用してコンパイルし、TLB を生成することができます。

.NET 6 以降のバージョンでは、.NET SDK によってプロジェクト ビルドの一部として、既にコンパイルされた TLB を COM ホストに埋め込むことがサポートされています。

タイプ ライブラリをアプリケーションに埋め込むには、次の手順を実行します。

  1. .csproj プロジェクト ファイルを開き、<ItemGroup></ItemGroup> タグの内側に <ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" /> を追加します。
  2. <id> を正の整数値で置き換えます。 この値は、COM ホストに埋め込むために指定する TLB 間で一意である必要があります。
    • プロジェクトに ComHostTypeLibrary を 1 つだけ追加する場合、Id 属性は省略可能です。

たとえば、次のコード ブロックは、インデックス 1Server.tlb タイプ ライブラリを COM ホストに追加します。

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

既定での読み込み AssemblyLoadContext

アクティブ化の間に、COM コンポーネントを含むアセンブリがアセンブリ パスに基づいて個別の AssemblyLoadContext に読み込まれます。 1 つで複数の COM サーバーを提供するアセンブリがある場合、その AssemblyLoadContext は、そのアセンブリのすべてのサーバーが同じ読み込みコンテキストに存在するように再利用されます。 COM サーバーを提供するアセンブリが複数ある場合は、アセンブリごとに新しい AssemblyLoadContext が作成され、各サーバーはそのアセンブリに対応する読み込みコンテキストに存在します。

.NET 8 以降のバージョンでは、アセンブリは、既定 AssemblyLoadContextの に読み込む必要があることを指定できます。 既定のコンテキストでの読み込みを有効にするには、次の RuntimeHostConfigurationOption 項目をプロジェクトに追加します:

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

サンプル

GitHub の dotnet/samples リポジトリには、完全に機能する COM サーバーのサンプルがあります。

追加メモ

重要

.NET Framework では、32 ビットと 64 ビットの両方のクライアントで "Any CPU" アセンブリを使用できます。 .NET Core、.NET 5、およびそれ以降のバージョンでは、既定で "Any CPU" アセンブリに 64 ビットの .comhost.dll が付属しています。 このため、これらを使用できるのは 64 ビットのクライアントでのみとなります。 これは SDK で示されるものであるため、既定値となります。 この動作は、"自己完結型" 機能が公開される方法と同じです。既定では、SDK によって提供されるものが使用されます。 MSBuild の NETCoreSdkRuntimeIdentifier プロパティによって、*.comhost.dll のビットが決まります。 マネージド部分は実際には想定どおりにビットには対応していませんが、付随するネイティブ資産の既定値はターゲットとなる SDK になります。

COM コンポーネントの自己完結型の配置はサポートされていません。 COM コンポーネントのフレームワークに依存する配置のみがサポートされています。

また、.NET Framework と .NET Core の両方を同じプロセスに読み込むと、診断が制限されます。 主にマネージド コンポーネントのデバッグが制限されます。これは、.NET Framework と .NET Core の両方を同時にデバッグすることはできないためです。 また、2 つのランタイム インスタンスはマネージド アセンブリを共有しません。 つまり、2 つのランタイム間で実際の .NET 型を共有することはできません。代わりに、すべての対話を、公開されている COM インターフェイス コントラクトに制限する必要があります。