This blog is about developing Windows applications using Visual Studio. All postings on this weblog are provided "AS IS" with no warranties, and confer no rights. Use of any samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
Your host Nikola Dudar is a Program Manager in Windows division of Microsoft Corporation. He has been working on Windows Web Services API during Windows 7 and various additions to Visual C++ during VS2005 and VS2008. More details are in LinkedIn profile under Nikola's formal name Mykola Dudar.
If you are interested in program management and project management, check out my other blog at http://www.pmsnack.com/ where I collect best practices and other topics interesting to program and project managers.
To send feedback, comments or requests for new posts, please use the contact form.
I have received several questions about a case when developers find two or more references to different versions of CRT or MFC or ALT libraries in application manifest. Usually application manifest would look similar to the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
Notice underlined version of assembly. This manifest tells Windows loader to load two different versions of the same assembly. The loader is going to do what it is told to. But the problem arises when it can only find one version (50608) of them. There are two cases when this may happen:
1) The oldest version of VC++ library is installed in WinSxS folder. For example, author of the application may have redistributed VS2005 RTM version of CRT library using MSMs or VCRedist.EXE, but ones parts of application were rebuilt with VS2005 SP1 and deployed to the same machine, SP1 versions of MSMs or VCRedist.EXE were not deployed to the same machine.
2) It is not possible to have two versions of a private assembly in one folder. For example, an author of an application has deployed the RTM version of CRT library as a private assembly in application’s local folder. After application is rebuilt with SP1, the author faces a challenge of having two copies of same files/folders in application local folder. If she keeps RTM version, Windows loader is going to complain about SP1 version missing. If she keeps SP1 version, Windows loaders is going to fail to find RTM version. Windows shows a message box which says :”The application has failed to start because of side-by-side configuration is incorrect,” and event viewer shows error details similar to “Activation context generation failed for "…\foo.exe".Error in manifest or policy file. A component version required by the application conflicts with another component version already active.” Bottom line, application does not start.
The root cause of the issue is that not all parts of application’s source code are built with the same version of VC++ libraries and tools. The linker catches some cases and reports errors when it tries to link objects and libraries built with different versions of compiler. However it is still possible to get pass the linker and an application may get these two dependencies in its manifest.
There is one solution to the problem and two workarounds.
The solution. To fix the problem, you must rebuild all parts of your code with the newest toolset and libraries. Make sure you have cleaned up all binaries built by the old toolset and started full rebuild of the whole source base. Also check that old versions of headers and import libraries for VC++ libraries are not on INCLUDE and LIB path and they are not used during the build.
If you cannot rebuild all your code and use one version of VC libraries, there are two ways to work around this problem:
Workaround#1: Install the newer version (8.0.50727.762 in this case) of VC++ MSMs or VCRedist.EXE on a machine where your application is going to run. Once policy for VC++ assemblies is installed on that machine they are going to redirect all loads of older versions (8.0.50608.0) to the newest version available on the machine.
Workaround#2: If you are redistributing VC++ libraries in application’s local folder, you need to add an application configuration file that redirects an attempt to load 8.0.50608.0 version to 8.0.50727.762 version. Configuration file has to have same name as the exe plus .config extension and has to be right next to exe or embedded into the EXE. Here is an example of a configuration file that one would use to resolve issue with the manifest from above:
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
<bindingRedirect oldVersion="8.0.41204.256-8.0.50727.762" newVersion="8.0.50727.762"/>
This file basically redirects attempts to load any version of VC CRT greater or equal to 8.0.41204.256 (VS2005 Beta 1) and less than 8.0.50727.762(VS2005 SP1) to load VS2005 SP1 version of VC CRT. It is similar to what the policy file does for a case when CRT is installed into WinSxS folder.
Overall my recommendation is to never use static libraries for which you do not have a source code. Using a static library without its source always puts a set of restrictions on build configuration of a binary that consumes it. There are ways to build a “clean” static library, but they are not well known among developers and it is very rare to find a static library that can be consumed in a code built with different versions of compiler, linker and libraries. If source code is not provided, I would only take a dependency on a DLL and only if its APIs are cleanly designed to obey rules of data exchange across DLL boundary. COM and .Net class assemblies are designed to address this problem and they are the easiest technologies to use in this scenario.
When VS2005 SP1 has been released, because of manifests it become more visible what version of VC++ DLLs
Sorry I will have the nerve to post before reading every detail of your article. Yesterday I had a problem which was halfway like what you describe, but the solution was different.
> This manifest tells Windows loader to load two different versions of the same assembly. The loader is
> going to do what it is told to. But the problem arises when it can only find one version (50608) of them.
As far as I could tell, 50608 didn't exist. 50608 seemed to be used as a placeholder, which was _always_ redirected to 50727.something. The somethings were not all equal, but the 50727s were always equal.
In someone else's MSDN blog I found something else that was halfway related, and one of the suggestions worked. In manifests that called for versions 50727.something, I edited the manifests to call for version 50608.0, even though 50608 didn't exist. 50608 was always redirected to 50727.something -- an existing something, not the something that was failing. So then it worked.
In my experience, this had to be done for the MFC manifest for a program that used MFC, but it was optional for the CRT.
Now your article has me worrying again because if two parts of a program depend on different version numbers of MFC (or CRT) then do I have to try to get both versions loaded, and I have a feeling I won't be able to get them loaded. I hope it will be enough to get one version loaded, the one that 50608 redirects to, and hope it's the latest version.
> Using a static library without its source always puts a set of restrictions on build configuration of a binary
> that consumes it.
DLLs do too. There is no silver bullet.
If an application is built with VS2005 RTM, 50608.0 version is embedded into application manifest. At runtime it is redirected to 50727.42 version by publisher policy. If you deploy VC DLLs in applocal folder manifests in vc\redist folder will match version to 50608.0. I think only Debug DLL for OpenMP was not matching that version because of bug. This is common to all VC libraries.
For applications parts of which are built with RTM and parts with SP1 versions of VS2005, only SP1 versions should be installed. Both parts are going to load SP1 version and because it is binary compatible with RTM version.
It is true that if DLL exposes complex CRT or MFC or STL type in its exports, it may put restrictions on build configuration of a consumer EXE. However this is a design issue. Only simple built-in types can be used in DLL exports.
Thank you for replying to my comment on March 30. I'm still trying to figure it out. I don't know what OpenMP is and we weren't trying to redistribute debug versions of anything (in fact I had to explain to colleagues about the sad prohibition on redistributing debug versions), so that was not the manifest which I had to edit.
The problem involved an application that was built with VS2005 SP1. Our customer doesn't want to redistribute SP1 versions of vcredist.exe to their customers so I hacked together a list of necessary redistributables, CRT, MFC, and MFC localizations. On a target system without VS2005, the search for CRT version 50608.0 was redirected to 50727.something and seemed happy to use 50727.762 (I think). The search for MFC was failing. On another MSDN blogger's site I found a suggestion to edit the manifest to specify version 50608.0, and it worked. I stopped debugging at that point so haven't checked what redirections are happening now.
Since the RTM version of vcredist.exe is downloadable, I'm thinking of recompiling this particular application on a Windows XP system with VS2005 RTM. At the moment this isn't a priority for my employer and our customer, since the above hack seems to be working.
I disagree that is is necessary that all static libs must be created with the same compiler version. In this case I mean the different versions of VS2005! Not older versions!
There is a simple trick to get around the messy with the injected manifest statements!
If the programmer defines _CRT_NOFORCE_MANIFEST in the static library and the main program is created with the any VS2005 compiler and linker and the usual CRT settings are set, than no multiple CRT versions are requested.
I wrote already an article about this in my blog in German :-)
Martin MVP C++
I did mention in the post that there are ways to build a “clean” static library, but they are not well known and not documented. And I have mentioned that in my post with Q&A about VS2005 SP1. Techniques of using _CRT_NOFORCE_MANIFEST and other non-documented #defines for other libraries may help to remove dependency on a version of VC library from a static library. However it is not documented configuration and almost none is using it. And because there is a very small number of static libraries that use *_NOFORCE_manifest, using a static library is problematic if its source code is not available.
> If she keeps RTM version, Windows loader is going to complain about SP1 version missing. If she keeps
> SP1 version, Windows loaders is going to fail to find RTM version. Windows shows a message box which
> says :”The application has failed to start because of side-by-side configuration is incorrect,” and event
> viewer shows error details similar to “Activation context generation failed for "…\foo.exe".Error in
> manifest or policy file. A component version required by the application conflicts with another
> component version already active.”
Yesterday this happened to a colleague and I wasted hours trying to find ways to fix it. My colleague had graded his development machine to VS2005 SP1 and we were testing on a Vista machine with no VS2005 components of any kind. I had done the same thing a week earlier and only needed a few hours of reading and experimenting to get it working, but here it was broken again, and the same number of hours weren't enough.
Finally I noticed that the error message in the event viewer matched the one you described in this part of your posting, except of course for the language version of the message.
Then it dawned on me. I checked my colleague's machine. He had graded to SP1 and had done a new build, but had not done a new rebuild. I did a rebuild, so every .obj file depended on SP1 versions of libraries. The resulting .exe (or in other cases a resulting .dll) no longer had two sets of dependencies. All was well.
I think I have to agree with postings I've seen by some others, though I'll adjust some wording. Dll Hell .Net is worse than Dll Hell Classic.
I also agree that Dll Hell .Net is worse than Dll Hell Classic. I've had the worst time deploying applications that didn't require a second thought in the past. When experienced developers are spending days trying to sort through all of these dll issues on every visual studio 2005 project they create, then its a serious problem. Whoever designed the side by side system did a huge disservice to the developers. It has placed a heavy burden on them to try and untangle what is going on. The upgrade, SP1 made the situation worse. None of the apps I deployed without the service pack worked after I installed it, and I had huge problems trying to remove the service pack and get my old version of vs 2005 to work.
I beg you at microsoft to rethink the side by side assembly, or somehow improve our ability to deploy applications because its costing companies a lot of money and time, when those resources could be better spent solving true problems.
I seriously think the manifest system is significantly flawed. The idea is nice, but the implementation is poor. Please fix this system.
I have another problem.
I have a dll built using VC2005 SP0 (call it dll A ). This dll calls another dll built using VC 2005 SP1 (call it dll B). The whole thing is a part of a custom action during an msi install. I package VC 2005 SP1 mergemodules (VCRT and policy) with my installer. This works great on W2K3 and W2K, dll A can LoadLibrary B and work fine. But on Vista, this will fail. The only work around I have seen is to use the VCRTRedist_x86.exe before I call my installer package. Including the mergemodule within my installer fails.
It does seem odd that something like this would fail only on vista, but from looking at the msm, it looks like some of the components do have launchconditions which cause them to behave differently on Vista.
The mergemodule and the exe look identical from what I can see, but I guess this is something to do with sequencing within the installer, maybe the manifest is not getting updated by the time I call my customaction?
You analysis is right. VC MSMs use different ways of installing DLLs into WinSxS folder for WinXP/Win2k3 and Vista. We are working around a bug in WinSxS folder on WinXP. On Vista, MSMs are using the native MSI support for installing Win32 assemblies into WinSxS store. Native MSI support for Win32 assembly installs uses a 2-phase commit and assemblies are not available until the commit process has completed. Custom actions that rely upon a global assembly must be either of type commit or immediate custom actions sequenced after InstallFinalize or statically link to VC libraries. Services that rely upon the assembly cannot be started using the ServiceControl table. They must be started using a commit custom action or an immediate custom action sequenced after InstallFinalize. Check out MSDN documentation for the ServiceControl table http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/servicecontrol_table.asp and MsiAssembly table docs http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/msiassembly_table.asp and commit custom action type can be found http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/custom_action_in_script_execution_options.asp. Check out also Custom Action Guidelines on Heath’s blog, http://blogs.msdn.com/heaths/archive/2007/04/20/custom-action-guidelines.aspx.
Now thats a fast response if there is one!!
But you do realize what a problem this can be right? I just moved all my custom actions to before installfinalize to get around UAC issues (These custom actions need to modify systemwide settings, so need to be deferred actions in system context ). If I move it later after installfinalize , the installs will fail if the installs are being done by Local Administrator Group Members and not Domain/Local Admins.
If I understand correctly, If I wrote a service which requires global assembly (in my case this is a problem I dont think I have), you have to pick one of 2 --
a) Lose the ability to work within UAC (ie Members of local domain admins cannot install your app)
b) Have the user install VCRTRedist_archtype.exe seperately (or do this from an install bootstrapper outside the msi package )
It is unfortunate that this had to happen on Vista. As a developer, I understand that the rules get stricter on Vista and I am willing to work with that, but when msi, VC2005 SP1 and UAC rules mix, that leaves no room for me :-(
In my case I am taking option b), Install the exe external to my msi. Is there an accurate (or recommended) way of determining if a customer has already installed this app, so that I don't end up prompting the user to install it again?
If you need to run CAs before InstallFinalize, you may need to install VCRedist.exe upfront, for example, using a simple bootstrapper, or you may statically link these CAs to VC libraries. Check with MSI team,http://blogs.msdn.com/windows_installer_team, and/or Aaron,http://blogs.msdn.com/astebner/, and Heath,http://blogs.msdn.com/heaths/. They may help you find another MSI supported way of building your MSI.
I have tried the redirect solution which you describe using an app.exe.config file with the .762 VC80 CRT deployed as a local assembly. I confirmed that the config file was being used by making a syntax error in the XML (!)
Unfortunately this doesn't seem to work in my case when my app.exe loads a DLL which contains an embedded manifest depending upon both 50608.0 and 50727.762 everything fails with an error 0xc0150002.
Is there a tool like depends for chasing down these manifest dependency problems? Manifest hell has now replaced Dll hell, but at least for Dll hell depends.exe could show what the problem was, in this situation everything seems to be stabs in the dark!
Even a famous very small software maker has trouble with Dll Hell .Net.
ActiveSync 4.5 depends on MFC and MFCLOC. ActiveSync 4.5 doesn't properly install MFCLOC. After installing ActiveSync 4.5, every reboot yields twelve SideBySide errors in the system log.
Has someone tried #2 succesfully?