Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I target a specific version of the C++ runtime?

We have a very large project mostly written in C# that has some small, but important, components written in C++. We target the RTM of .NET 2.0 as the minimum required version. So far, in order to meet this requirement we've made sure to have only the RTM of .NET 2.0 on our build box so that the C++ pieces link against that version.

Update: The C++ assembly that is causing the issue is a mixed-mode C++ assembly being loaded into a managed process.

Unfortunately when the confiker was set to do something on April 1st, our corporate IT made a huge push to get everything patched and up to date, and as a result everything up through 3.5 SP1 got installed on the build box. We've tried uninstalling everything, which has happened before, but now we are unable to meet our minimum requirements as anything built on that particular box requires .NET 2.0 SP1.

Since the box seems to be hosed in that we can't just uninstall the offending versions, is there any way to build the assemblies and explicitly tell them to use the RTM of .NET 2.0 (which is v2.0.50727.42)? I've seen pages that refer to using a manifest, but I can't figure out how to actually implement a proper manifest and get it into the assemblies. My expertise is in the managed world, so I'm at a bit of a loss on this.

Can anyone explain how I can make these assemblies target the .NET 2.0 RTM SxS assemblies?

Thanks!

like image 623
John Clayton Avatar asked Dec 05 '22 05:12

John Clayton


1 Answers

While I'm pretty sure that Christopher's answer and code sample (thank you, Christopher!) is part of a more elegant solution, we were under the gun to get this out the door and found a very similar, but different, solution.

The first step is to create a manifest for the assembly:

<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>

Next you have to set the 'Generate Manifest' option to 'No' under Configuration Properties -> Linker -> Manifest File, and set the 'Embed Manifest' option to 'No' under Configuration Properties -> Manifest Tool -> Input and Output.

Finally, to get your new manifest into the assembly add the following command to the project's post-build step:

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

Once built we can open the dll in Visual Studio to view the manifest under RT_MANIFEST and confirm that it has our manifest!

When I put Christopher's code in the stdafx.h it ended up adding it as an additional dependency...the manifest was still looking for v8.0.50727.762. The manifest it generated looked like this:

<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>

I could not track down another switch that would remove or clear existing dependencies. I like Christopher's approach better than a post-build step, but for now this works. If anyone has any additional input on how to clear out any existing dependencies that'd be great.

Thanks!

like image 150
John Clayton Avatar answered Dec 07 '22 17:12

John Clayton