如何定位特定版本的C ++运行时?

时间:2009-07-06 15:30:36

标签: .net c++ side-by-side

我们有一个非常大的项目,主要是用C#编写的,它有一些用C ++编写的小而重要的组件。我们将.NET 2.0的RTM作为最低要求版本。到目前为止,为了满足这一要求,我们确保在构建盒上只有.NET 2.0的RTM,以便C ++片段链接到该版本。

更新:导致此问题的C ++程序集是一个加载到托管进程的混合模式C ++程序集。

不幸的是,当confiker在4月1日开始做某事时,我们的公司IT部门大力推动修补所有内容并进行更新,因此在构建框中安装了3.5 SP1的所有内容。我们已尝试卸载以前发生的所有事情,但现在我们无法满足最低要求,因为构建在该特定框上的任何内容都需要.NET 2.0 SP1。

由于这个方框似乎已经被清除,我们不能只卸载有问题的版本,有没有办法构建程序集并明确告诉他们使用.NET 2.0的RTM(这是v2.0.50727.42) )?我已经看到了引用使用清单的页面,但我无法弄清楚如何实际实现适当的清单并将其放入程序集中。我的专长是在管理世界,所以我对此感到有些失落。

任何人都可以解释如何使这些程序集成为.NET 2.0 RTM SxS程序集的目标吗?

谢谢!

6 个答案:

答案 0 :(得分:8)

虽然我很确定克里斯托弗的答案和代码示例(谢谢你,克里斯托弗!)是一个更优雅的解决方案的一部分,但是我们还在努力将它推出门外,发现了一个非常相似但不同的,溶液

第一步是为程序集创建清单:

<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

接下来,您必须在Configuration Properties - &gt;下将'Generate Manifest'选项设置为'No'。链接器 - &gt;清单文件,并在配置属性下将'嵌入清单'选项设置为'否' - &gt;清单工具 - &gt;输入和输出。

最后,要将新清单添加到程序集中,请将以下命令添加到项目的构建后步骤中:

mt.exe /manifest "$(ProjectDir)cppassembly.dll.manifest" /outputresource:"$(TargetDir)\cppassembly.dll";#2 -out:"$(TargetDir)\cppassembly.dll.manifest"

一旦构建完毕,我们就可以在Visual Studio中打开dll来查看RT_MANIFEST下的清单并确认它有我们的清单!

当我将Christopher的代码放在stdafx.h中时,它最终将其添加为附加的依赖项......清单仍然在寻找v8.0.50727.762。它生成的清单看起来像这样:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

我无法跟踪另一个会删除或清除现有依赖项的开关。我更喜欢克里斯托弗的方法而不是后期构建步骤,但现在这种方法很有效。如果有人有任何关于如何清除任何现有依赖关系的额外信息。

谢谢!

答案 1 :(得分:3)

是。在项目属性中,有一个指示运行时的页面。有一个下拉列表列出了所有可用的运行时。选择适合您的那个。 (对于VS 2008:右键单击项目 - &gt;属性,编译选项卡,高级编译器设置按钮 - &gt;目标框架)

我们现在就这样做。我们想转向VS 2008,但我们正在逐步进行。所以现在我们有一个VS 2008解决方案,但所有项目仍然以.Net 2.0为目标。因此,当我们编译和部署时,我们不需要在我们的测试盒上安装.Net 3.5内容。

<强>更新

要强制本机程序链接到特定版本的.dll,您可能希望使用以下内容:

#pragma message ("Explicit link to generate a manifest entry for MFC.")

#if defined (_DEBUG)

#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.VC80.DebugMFC' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'\"")

#else

#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.VC80.MFC' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'\"")

#endif

除了MFC之外,您应该找到.Net .DLL的正确值。

有理由相信你不能在同一个盒子上安装.Net 2.0 SP1和.Net 2.0。因此,让它在该盒子上工作可能会非常非常痛苦。最好是启动一个新的构建VM,你可以安装旧的,未修补的.Net框架(如果你甚至可以再拿到它。)

否则,您需要将所有构建时文件复制到当前框中,然后根据构建类型调整包含和库路径。可能这是一个比它值得更大的头痛。

答案 2 :(得分:2)

John真的让我走上正确的道路来解决同样的问题。我正在对旧的VS2005 C ++(非CLR)项目进行一些改动。我的开发机器有所有更新,所以VS2005正在创建对最新版本的MFC80和MSVCx80 DLL的引用,并且可执行文件不能在目标机器上运行,因为那些版本不可用,我没有更新这些机器的选项。所以我需要控制嵌入在可执行文件中的清单中的assmelby依赖项。这似乎与John正在研究的问题大致相同。从他的附加信息开始,这对我有用。

在ProjectDir中,使用适当的程序集参考信息创建 program.exe.debug.manifest program.exe.release.manifest 文件。不要将这些添加到项目或链接器中,并尝试在每个构建中包含它们。然后按如下方式设置项目属性:

链接器&GT;清单文件选项

  • 生成清单:否
  • 清单文件:空白
  • 其他Manifest依赖项:空白
  • 允许隔离:是

清单工具 - &gt;输入和输出选项

  • 其他清单文件:$(ProjectDir)$(TargetFileName)。$(ConfigurationName).manifest
  • 输入资源清单:空白
  • 嵌入清单:是
  • 输出清单文件:(自动填写)
  • 清单资源文件:(自动填写)
  • 生成目录文件:否
  • 依赖关系信息文件:$(IntDir)\ mt.dep(自动填写)

从我的测试中看来,这不会生成任何其他清单文件,并将您的手动编码清单信息作为RT_MANIFTEST资源#1嵌入到EXE中。

在清单工具选项中,即使在我清除它们之后,“输出清单文件”和“清单资源文件”也会自动填写。

这似乎允许我控制程序集依赖关系并使可执行文件在目标计算机上运行。额外的好处是我不必使用用于其他目的的构建后步骤。通过操作Linker和Manifest Tool选项,可以得到相同的结果。

抱歉,我无法更新屏幕截图,但我是新用户,目前还不允许使用图片。

答案 3 :(得分:1)

我知道这是一个黑客,但我已经采取外部生成清单,并用记事本修改它。在紧要关头,它为我完成了诀窍。在我的情况下,我希望VC ++ 2005应用程序指向.762 CRT。

祝你好运! 特里

答案 4 :(得分:1)

约翰的回答对我们有用。在Visual C ++ 2005中,编译器生成包含MFC和CRT的762和4053版本的清单。我们从清单中删除了4053版本,并进入上述手动步骤。 (内部代码实际上会占用4053,因为它是762以上的公认安全修复程序,但规范是必要的,否则链接就会失败。)

Ted的博客(tedwvc.wordpress.com)帖子给了我们提示,但他的解决方案并没有为我们解决问题。这种方法可行。

答案 5 :(得分:0)

你想要的方法CorBindToRuntime。这将允许您指定C ++加载的CLR的版本。