2

有谁知道为什么在 CLR2 (.Net 3.5) 下编译的 C# 创建的 COM 库在仅与 CLR4(.Net 4) 一起使用时不起作用?COM 的 CLR2 中的 CLR4 中缺少什么?

我们在 app.config 中使用适当的启动来让 C# 在 CLR4/.Net 4 下运行:

<startup>
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>

在尝试创建我们的 COM 接口之前,所有 C# 的东西都有效。它提供了以下例外:

无法加载运行时。(来自 HRESULT 的异常:0x80131700)

当我们尝试从 C++ 创建 COM 接口时,我们会遇到同样的问题。

一旦我们安装了 CLR2 (.Net 3.5),所有的 COM 东西都开始工作了。我们想知道发生了什么。

4

3 回答 3

3

该程序集已注册为需要CLR v2,但您明确禁止使用 .config 文件加载该版本。您需要在 .config 文件中添加一个额外的信息来表示“我知道,但没关系”。像这样:

<startup useLegacyV2RuntimeActivationPolicy="true">
   <supportedRuntime version="v4.0"/>
</startup>  

请注意,您有意绕过 .NET 4 中添加的进程内并行版本控制功能。明确添加了一项新功能,以允许应用程序加载多个版本的 CLR 以支持具有不同的 COM 服务器CLR 版本要求。这当然听起来像你的情况。在这种情况下,更兼容的鼠标陷阱是允许加载两个版本的 CLR:

<startup>
   <supportedRuntime version="v4.0"/>
   <supportedRuntime version="v2.0.50727"/>
</startup>  

另一个非常重要的细节是这个 .config 文件的名称和位置。这是不直观的,但 CLR 从启动 EXE 的目录和名称中找到 .config 文件。因此,如果您从本地 C++ 程序(例如 c:\foo\bar.exe)测试此 [ComVisible] 服务器,则必须将文件命名为“bar.exe.config”并将其复制到 c:\foo 目录。将 .config 文件与具有 DLL 名称的 DLL 放在同一目录中将不起作用

于 2012-11-05T18:14:57.717 回答
3

在 .NET 4 中编译程序集后,您可能需要使用 regasm.exe 来更新 RuntimeVersion。如果重新编译不是一个选项,您可能会将注册表中的 RuntimeVersion 从 v2.0.50727 更改为 v4.0.30319。这对我有用。我在这里找到了类似的答案:Using a .NET-2.0-targeted COM DLL in the GAC on a .NET-4-only system

于 2012-11-05T19:06:41.163 回答
0

CLR 版本写在 .dll 文件头中,其值由 regasm 工具复制到注册表。然后激活器尝试使用指定的确切 CLR 版本运行组件。要让 CLR 4 运行在 CLR 2 程序集中实现的组件,您可以手动更改注册信息 (Classes/{clsid}/InprocServer32/component-version/RuntimeVersion) 或useLegacyV2RuntimeActivationPolicy按照上一个答案中的描述进行设置(配置文件确实可以转到本机 .exe 旁边,这没什么问题)。

于 2012-11-05T19:13:32.713 回答