问题描述
我正在尝试调试平台设置为“任何cpu”的.NET Core 3.1的COM服务器。我有一个用ComVisible
和Guid
属性修饰的类,在.csproj中有<EnableComHosting>true</EnableComHosting>
。构建项目时,我得到了Exposing .NET Core components to COM中提到的所有文件,并且在运行regsvr32
之后,注册表已正确更新,并且InprocServer32
设置为My.Namespace.comhost.dll
。
C ++端调用CoCreateInstance()
:
IUnkNown* ptr;
HRESULT hr = CoCreateInstance(clsid,CLSCTX_ALL,iid,(void**)&ptr);
如果客户端被编译为64位应用程序,则调用成功。如果将其编译为32位应用程序,则尽管InprocServer32
和HKCR\CLSID\{class-id-value}
中都设置了HKCR\WOW6432Node\CLSID\{class-id-value}
,但调用失败并显示“ Class notregistered”(这是具有同一COM服务器的两个版本)。
但是,如果我将COM服务器定位为“ x86”而不是“任何cpu”平台,然后重新编译(具有完全相同的文件路径和程序集名称),则C ++客户端可以实例化它。
>所以:
当然,我可以设计一种解决方法-拥有两个带有“前端” COM服务器的项目,或者具有两个配置,这两个配置将两次构建相同的项目,或者使其他事物相同,从而使同一COM服务器暴露为“ x64”和“ x86”程序集。最好使“任何cpu”版本都能正常工作。
难道没有更直接的方法可以从32位和64位COM客户端使用“任何cpu”类库吗?
解决方法
COM客户端无法直接加载IL,因此总会有一些中介程序加载IL代码并将其转换为本地代码。
使用.NET Framework时,它是mscoree.dll,它安装在\ windows \ system32中,非常稳定,并且我认为Windows附带了一段时间。因此,这是所有.NET Framework COM(过程中)对象的共同点
通过.NET Core,无论是否不幸,都有一个本机宿主必须随项目一起提供,它称为[project] .comhost.dll。
.NET assemby的“ Any Cpu” /“ x86” /“ x64”选项确实会影响此设置,但它不能支持comhost.dll的“ Any Cpu”设置,它必须为x86或x64 。
这是一个很小的视觉效果:
基本的设计思想是恕我直言,以最大程度地增强.NET(核心)与OS(此处为Windows)之间的松散耦合。它肯定有一些弊端,不仅限于COM。
以下是官方dotnet github上有关此主题的讨论:Support dual comhost.dll (x86,x64) generation for .NET Core assemblies using "Any CPU