Microsoft provides a variety of libraries with versions of Visual Studio that developers can reference in their programs. Of course, over time these libraries are updated and replaced with newer versions, but generally if an application was written to use a specific version it needs that specific version. Microsoft provides “redistributable” installers for these libraries, so that developers can ship the version that they need with the application.
In the “old days” before DotNet, MFC apps used dlls with names like vb6.dll or msvcp60.dll. The names reflected a programing language or purpose, and a major version. When the redistributable was updated within a major version, the file name remained the same and the application installer was supposed to check for an existing version and only update the file if the app had a newer version. The idea was that any newer version within a major version (i.e. same file name) would be backward compatible with older versions. Unfortunately sometimes the newer version wasn’t backward compatible and sometimes app installers didn’t check versions but just slammed theirs down. This was the major cause of what was called “DLL hell”. Sometimes ISVs would use another technique to imbed the libraries within their program to eliminate these issues, but Microsoft really hated this because if a security issue was discovered within the library, they depended on the ISV to patch their program with the update also. Microsoft didn’t like this.
A design goal of DotNet was to eliminate these problems. DotNet based Dlls would include full versioning information as part of the name, so that they could co-exists “side by side”. Applications could specify a range of acceptable versions and get the latest compatible version available. The Visual Studio runtimes, which we can simplify by calling them the 2005, 2008, 2010, and now 2012 versions can all be on the same box at the same time without interfering. But a funny thing happened on the way to solving dll hell for us. DotNet found other ways to really mess us up over versions:
- Over time, reasons have cropped up to not want all of the possible available older minor versions to be hanging around. This happens when the original version has a zero-day like security bug. When the patch comes out, it will have a new version and therefore new file names, but the installer really wants to locate and remove the unpatched versions to ensure that an app doesn’t continue to use it.
- App-V loves to capture these DotNet dlls, but in recent versions appears unable to make them work inside the App-V packages at the Client. Vendor DotNet dlls aren’t an issue, just these VC++ Runtime ones.
This latter issue is the cause of this post. A few years ago, this wasn’t a problem. Then it was a problem only for apps sequenced on one OS and used on another. Then we started having problems with packages sequenced on one App-V version and run on a higher version. Currently, as of 4.6SP1 and 5.0 Beta, we are forced to recommend that these DotNet based VC++ runtimes are kept out of App-V packages. [Note: I have discovered a way to make these work inside the package, but it is much more work than the method we now recommend].
Effectively, this means checking the “sequence editor” captured files to see if any of the VC runtime dlls were installed as part of the application. If so, we start over and natively install the runtime prior to sequencing, and then make sure that the same runtime is installed natively on every client image.
After struggling with some apps recently, I found it necessary to try to come up with a definitive list that will help. The list needs to include info so that you can:
- Determine what VC++ runtime version is being captured and how to relate it to an actual installer.
- Be able to understand when and how things get removed by some of these runtime installers. It is possible for the removal (as part of a security patch) to break an application so we do need to be aware of this.
- Understand ordering issues on the installers. Install A and patch B and you end up with B; Install patch B and A and you end up with both.
- Understand what versions certain App-V installers install themselves.
I found that there are a few things happening that make things even more confusing without a good chart:
- The names of the installers from Microsoft are the same for all versions. For example, they are all vcredist_x86.exe for the 32-bit versions of everything on the chart below.
- ISVs are free to rename the installer files, and to tell you it is the RTM version of a series even though it is the service pack or security update version. Some do this, probably out of carelessness.
- The version field on the installer didn’t match the version of the installed runtime for the 2005 series.
- Within a series, there may be both service packs and security updates. Each appear differently and the installers have different behaviors (but still that same installer filename). When you run the installer, it tends to not bother to mention that it is the service pack or security update.
- There are also Beta versions that you won’t find installers for from Microsoft downloads. ISVs sometimes include these with their products, even though they shouldn’t.
You want to be aware of the naming tendencies of files by major version:
- VC 2005 uses 80
- VC 2008 uses 90
- VC 2010 uses 100
- VC 2012 uses 110
In general, you can detect these runtimes by looking in up to three places:
- 2005, 2008, 2010, but not 2012: C:\Program Files\Common Files\Microsoft\vc : look for files like [name][#].dll
- 2005, 2008: C:\Windows\WinSxS] : look for folders like x86_microsofr.vc[#].[name]_[guid1]_[version]_[lang]_[guid2]
- 2010, 2012: C:\Windows\System32 : look for files like [name][#].dll
The x64 case is similar to x86, but be aware that on x64 you might need both x86 and x64 runtimes.
Below is a view of the table with detailed information that I have gathered on x86.
You may click on an image for a larger image: