views:

360

answers:

3

I'm using Visual Studio 2008 SP1 for C++. When compiling, Visual Studio needs to choose against which version of the CRT and MFC DLLs the application should be linked, version 9.0.21022.8 (= RTM), 9.0.30729.17 (= SP1) or 9.0.30729.4148 (= SP1 with security update). I'd like to know how you can choose which of both versions will be linked against. Does anyone know?

Note: this is important when using a private assembly, because you need to know which versions of the VC 9.0 DLLs to copy along with the .exe.

Note that the _BIND_TO_CURRENT_VCLIBS_VERSION flag only makes sure that the right version is included in the manifest. The DLL version selection at runtime is apparently not done based upon the version that is included in the manifest file. Even if the manifest file says that v21022 should be used, the .exe uses the v30729 .DLLs. I know this, because it uses std::tr1::weakptr, which is not present in v21022.

+1  A: 

The compiler uses the .h and .lib files to determine what CRT code to use. Change your include and lib search directory build settings for your project to look in the directories where the appropriate .lib and .h files exist.

That said, why do you feel the need to use anything but the latest CRT?

David Gladfelter
+2  A: 

By defining

#define _CRT_ASSEMBLY_VERSION "9.0.30729.1"

or

#define _MFC_ASSEMBLY_VERSION "9.0.30729.1"

you can link against a specified version.

Simon Linder
Or simply by defining _BIND_TO_CURRENT_CRT_VERSION to be 1 (= newest version) or 0 (= oldest version). Is that correct?
Dimitri C.
Yes, that is correct. But if you want to bind a specified version use the define from above. I got the case that I had to bind to 9.0.30729.1 but _BIND... to newest would be 9.0.30729.4148, so I had to use that define.
Simon Linder
+5  A: 

_BIND_TO_CURRENT_VCLIBS_VERSION sets the current version in the manifest - or the RTM version if not. And setting it in the manifest is the correct way to do this.

What you are seeing however is the effects of an assembly policy file :- When the VCRedist package containing the 2008 SP1 runtime is installed, it installs a policy file into the WinSxS store with a bindingRedirect entry that redirects attempts to load the RTM runtime to the SP1 runtime.

So applications that specify the RTM runtime in their manifest will load the SP1 runtime, and applications that specify the SP1 runtime, will load the SP1 runtime.

If you actually DO want to use the RTM runtime, even when the SP1 runtime and policy files are installed, then you need to specify the RTM version in your manifest, AND make use of an application configuration file. Basically "yourappname.exe.config" ( or "yourdllname.dll.2.config" if its an isolation aware dll causing grief). Application congifuration files can supply a bindingRedirect element that overrides any assembly version specified in the manifest, or policy files.

This config file will tell the OS to load the RTM runtime even if the SP1 runtime is installed :-

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
    <windows>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
                <bindingRedirect oldVersion="9.0.30729.1" newVersion="9.0.21022.8"/>
            </dependentAssembly>
        </assemblyBinding>
    </windows>
</configuration>

Note: oldVersion is allowed to be a range: oldVersion="9.0.30729.1-9.1.0.0"

See: Application Configuration Files documented on MSDN.

Chris Becke
Thank you so much for this explanation. This indeed explains the weird behavior I noticed.
Dimitri C.