將 .NET Core 元件公開給 COM
本文將逐步引導您瞭解如何從 .NET Core (或 .NET 5+) 將類別公開給 COM。 本教學課程會示範如何:
- 從 .NET Core 向 COM 公開類別。
- 在建置您的 .NET Core 程式庫時,一併產生 COM 伺服器。
- 自動為 Registry-Free COM 產生並存伺服器資訊清單。
必要條件
- 安裝 .NET Core 3.0 SDK 或更新版本。
建立程式庫
第一步是建立程式庫。
建立新的資料夾,並在該資料夾中執行下列命令:
dotnet new classlib
開啟 [
Class1.cs
]。將
using System.Runtime.InteropServices;
新增到檔案的頂端。建立名為
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(); }
使用您要實作之 COM 介面的介面 GUID,將
[Guid("<IID>")]
屬性新增到介面。 例如:[Guid("fe103d6e-e71b-414c-80bf-982f18f6c1c7")]
。 請注意,因為對 COM 而言,此 GUID 是此介面的唯一識別碼,所以其必須是唯一的。 在 Visual Studio 中,您可以前往 [工具] > [建立 GUID] 開啟建立 GUID 工具,以產生 GUID。將
[InterfaceType]
屬性新增到介面,並指定您介面應實作的基底 COM 介面。建立名為
Server
且實作IServer
的類別。使用您要實作之 COM 類別的識別碼 GUID,將
[Guid("<CLSID>")]
屬性新增到類別。 例如:[Guid("9f35b6f5-2c05-4e7f-93aa-ee087f6e7ab6")]
。 一如介面 GUID,因為對 COM 而言,此 GUID 是此介面唯一的識別碼,所以其必須是唯一的。將
[ComVisible(true)]
屬性新增到介面和類別。
重要
不同於 .NET Framework,.NET Core 會要求您為您希望可以透過 COM 啟動的所有類別指定 CLSID。
產生 COM 主機
- 開啟
.csproj
專案檔,然後在<PropertyGroup></PropertyGroup>
標籤內新增<EnableComHosting>true</EnableComHosting>
。 - 組建專案。
產生的輸出包含 ProjectName.dll
、ProjectName.deps.json
、ProjectName.runtimeconfig.json
和 ProjectName.comhost.dll
檔案。
為 COM 註冊 COM 主機
開啟提升權限的命令提示字元,然後執行 regsvr32 ProjectName.comhost.dll
。 這會向 COM 註冊您所有的公開 .NET 物件。
如果您想要 內嵌類型庫 (TLB),建議您也使用 ComRegisterFunctionAttribute
和 ComUnregisterFunctionAttribute
來定義函式。 這些函式可用來註冊和取消註冊 COM 伺服器的 TLB。 如需完整的範例,請參閱 OutOfProcCOM
範例。
啟用 RegFree COM
- 開啟
.csproj
專案檔,然後在<PropertyGroup></PropertyGroup>
標籤內新增<EnableRegFreeCom>true</EnableRegFreeCom>
。 - 組建專案。
產生的輸出現在還包含 ProjectName.X.manifest
檔案。 此檔案為並存資訊清單,可與 Registry-Free COM 搭配使用。
在 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 主機,作為專案建置的一部分。
若要將型別程式庫內嵌至您的應用程式,請遵循下列步驟:
- 開啟
.csproj
專案檔,並且在<ItemGroup></ItemGroup>
標記內新增<ComHostTypeLibrary Include="path/to/typelib.tlb" Id="<id>" />
。 - 將
<id>
取代為正整數值。 在您指定要內嵌在 COM 主機中的 TLB 之間,此值必須是唯一的。- 如果您只將一個
ComHostTypeLibrary
新增至專案,則Id
屬性是選用的。
- 如果您只將一個
例如,下列程式碼區塊會將位在索引 1
的 Server.tlb
型別程式庫新增至 COM 主機:
<ItemGroup>
<ComHostTypeLibrary Include="Server.tlb" Id="1" />
</ItemGroup>
在預設 AssemblyLoadContext
中載入
在啟用期間,包含 COM 組件的組件會根據組件路徑,在個別 AssemblyLoadContext 中載入。 如果有一個組件提供多部 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 位用戶端都可以取用「任何 CPU」元件。 根據預設,在 .NET Core、.NET 5 和更新版本中,「任何 CPU」元件會隨附 64 位 *.comhost.dll。 因此,這些只能由 64 位元用戶端取用。 這是預設的行為,因為這是 SDK 所代表的內容。 這種行為與發佈「獨立式」功能的方式相同:根據預設,這會使用 SDK 所提供的功能。 NETCoreSdkRuntimeIdentifier
MSBuild 屬性會決定 *.comhost.dll 的位元。 受控元件實際上與預期無關,但伴隨的原生資產預設為目標 SDK。
不支援 COM 元件的獨立式部署。 僅支援 COM 元件的基礎結構相依部署。
不支援透過 EnableComHosting 屬性從 C++/CLI 專案公開 COM 元件。
此外,將 .NET Framework 和 .NET Core 載入到相同的流程確實有診斷限制。 主要限制是受控元件的偵錯,因為無法同時偵錯 .NET Framework 和 .NET Core。 此外,這兩個執行階段執行個體不會共用受控組件。 這表示無法跨兩個執行階段共用實際的 .NET 類型,而所有互動都必須限制為公開的 COM 介面合約。