Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App does not run with VS 2008 SP1 DLLs, previous version works with RTM versions

Since our switch from Visual Studio 6 to Visual Studio 2008, we've been using the MFC90.dll and msvc[pr]90.dlls along with the manifest files in a private side-by-side configuration so as to not worry about versions or installing them to the system.

Pre-SP1, this was working fine (and still works fine on our developer machines). Now that we've done some testing post-SP1 I've been pulling my hair out since yesterday morning.

First off, our NSIS installer script pulls the dlls and manifest files from the redist folder. These were no longer correct, as the app still links to the RTM version.

So I added the define for _BIND_TO_CURRENT_VCLIBS_VERSION=1 to all of our projects so that they will use the SP1 DLLs in the redist folder (or subsequent ones as new service packs come out). It took me hours to find this.

I've double checked the generated manifest files in the intermediate files folder from the compilation, and they correctly list the 9.0.30729.1 SP1 versions. I've double and triple checked depends on a clean machine: it all links to the local dlls with no errors.

Running the app still gets the following error:

The application failed to initialize properly (0xc0150002). Click on OK to terminate the application.

None of the searches I've done on google or microsoft have come up with anything that relates to my specific issues (but there are hits back to 2005 with this error message).

Any one had any similar problem with SP1?

Options:

  • Find the problem and fix it so it works as it should (preferred)
  • Install the redist
  • dig out the old RTM dlls and manifest files and remove the #define to use the current ones. (I've got them in an earlier installer build, since Microsoft blasts them out of your redist folder!)

Edit: I've tried re-building with the define turned off (link to RTM dlls), and that works as long as the RTM dlls are installed in the folder. If the SP1 dlls are dropped in, it gets the following error:

c:\Program Files\...\...\X.exe

This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

Has no-one else had to deal with this issue?

Edit: Just for grins, I downloaded and ran the vcredist_x86.exe for VS2008SP1 on my test machine. It works. With the SP1 DLLs. And my RTM linked app. But NOT in a private side-by-side distribution that worked pre-SP1.

like image 221
crashmstr Avatar asked Sep 12 '08 17:09

crashmstr


2 Answers

I just remembered another trick that I used to find out which static libraries were ill-behaving: 'grep' through the static libraries for the string '21022'. HOWEVER, don't use the 'normal' grep tools like wingrep because they won't show you these strings (they think it's a binary file and look for the raw, non-unicode string). Use the 'strings' utility from the resource kit (now in the Russinovich site I think). That one will grep through binaries ok. So you let this 'strings' go through your whole source tree and you'll see the binary files (dlls and static libraries) that contain references to the wrong manifest (or to the manifest with the wrong version in it).

like image 52
Roel Avatar answered Nov 16 '22 20:11

Roel


To understand the problem, I think it is important to realize that there are four version numbers involved:

  • (A) The version of the VC header files to which the .exe is compiled.
  • (B) The version of the manifest file that is embedded in the resources section of that .exe. By default, this manifest file is automatically generated by Visual Studio.
  • (C) The version of the VC .DLLs (part of the side-by-side assembly) you copy in the same directory as the .exe.
  • (D) The version of the VC manifest files (part of the side-by-side assembly) you copy in the same directory as the .exe.

There are two versions of the VC 2008 DLL's in the running:

  • v1: 9.0.21022.8
  • v2: 9.0.30729.4148

For clarity, I'll use the v1/v2 notation. The following table shows a number of possible situations:

Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1         | v2       | v1                    | v1          | v1         
2         | v2       | v1                    | v2          | v2          
3         | v2       | v1                    | v2          | v1
4         | v2       | v2                    | v2          | v2

The results of these situations when running the .exe on a clean Vista SP1 installation are:

  • Situation 1: a popup is shown, saying: "The procedure entry point XYZXYZ could not be located in the dynamic link library".

  • Situation 2: nothing seems to happen when running the .exe, but the following event is logged in Windows' "Event Viewer / Application log":

    Activation context generation failed for "C:\Path\file.exe".Error in manifest or policy file "C:\Path\Microsoft.VC90.CRT.MANIFEST" on line 4. Component identity found in manifest does not match the identity of the component requested. Reference is Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8". Definition is Microsoft

  • Situation 3: everything seems to work fine. This is remicles2's solution.

  • Situation 4: this is how it should be done. Regrettably, as Roel indicates, it can be rather hard to implement.

Now, my situation (and I think it is the same as crashmstr's) is nr 1. The problem is that Visual Studio for one reason or another generates client code (A) for v2, but for one reason or another, generates a v1 manifest file (B). I have no idea where version (A) can be configured.

Note that this whole explanation is still in the context of private assemblies.

Update: finally I start to understand what is going on. Apparently, Visual Studio generates client code (A) for v2 by default, contrary to what I've read on some Microsoft blogs. The _BIND_TO_CURRENT_VCLIBS_VERSION flag only selects the version in the generated manifest file (B), but this version will be ignored when running the application.

Conclusion

An .exe that is compiled by Visual Studio 2008 links to the newest versions of the VC90 DLLs by default. You can use the _BIND_TO_CURRENT_VCLIBS_VERSION flag to control which version of the VC90 libraries will be generated in the manifest file. This indeed avoids situation 2 where you get the error message "manifest does not match the identity of the component requested". It also explains why situation 3 works fine, as even without the _BIND_TO_CURRENT_VCLIBS_VERSION flag the application is linked to the newest versions of the VC DLLs.

The situation is even weirder with public side-by-side assemblies, where vcredist was run, putting the VC 9.0 DLLs in the Windows SxS directory. Even if the .exe's manifest file states that the old versions of the DLLs should be used (this is the case when the _BIND_TO_CURRENT_VCLIBS_VERSION flag is not set), Windows ignores this version number by default! Instead, Windows will use a newer version if present on the system, except when an "application configuration file" is used.

Am I the only one who thinks this is confusing?

So in summary:

  • For private assemblies, use the _BIND_TO_CURRENT_VCLIBS_VERSION flag in the .exe's project and all dependent .lib projects.
  • For public assemblies, this is not required, as Windows will automatically select the correct version of the .DLLs from the SxS directory.
like image 26
10 revs Avatar answered Nov 16 '22 20:11

10 revs