How to select against which version of the Visual C++ libraries the application is compiled? - c++

I'm using Visual Studio 2008 for C++. When compiling, Visual Studio compiles against the header files of the VC 9.0 libraries. However, there are different versions of this library available:
v9.0.21022.8 (= RTM)
v9.0.30729.17 (= SP1)
v9.0.30729.4148 (= SP1 with security update)
I'd like to know whether it is possible to tell Visual Studio which version it should compile against.
The reason I think this is important is because the application's installer needs to make sure that the correct version of the Microsoft Visual C++ 2008 Redistributable Package is installed. To me it feels like I don't have any control over this dependency, as apparently some Windows Update (not a Visual Studio update) can change this dependency. I'd like to keep using the same version to avoid the overhead of making the installer upgrading the Redistributable Package.
Note that this situation is different from my earlier question, as that one was about link time. Neither am I looking for a way to control the version that is put in the embedded manifest file, as that is explained here.

The manifest that's included with your binaries is automatically generated by the VS build system. Important headers that determine the version dependency that's emitted into the manifest are vc\include\crtassem.h and crtdefs.h. The former declares the CRT version. Note that it already has support for the RTM version vs the "latest" version with the _BIND_TO_CURRENT_CRT_VERSION macro. The latter contains #pragma comment directives to embed the /manifestdependency linker option into the .obj file, which in turn makes the linker auto-generate the manifest.
You don't have to do it this way, you can simply turn off the linker options that generate the manifest and write your own. That gives you complete control over the CRT version that your app binds to. Whether you are ahead with this is a bit questionable. You would probably still be shipping the old version of the CRT that got updated in July of last year, it contained a critical security bug. Customers tend to be a bit unhappy about getting software installed on their machine that has well documented and solved security flaws.
The next thing you'd have to do is take control of the deployment of the DLLs. You'll have to deploy the DLLs into the WinSxS side-by-side cache yourself.
That will work, if you figure out how, but it isn't likely to survive for very long. Windows Update, if enabled, may discover that the machine is using an unpatched version of the DLLs and will update it. And deploy a publisher policy to redirect load requests. It is likely that your machine has such a policy file in place if you see your manifested version request resulting in the load of another version. The somewhat unescapable conclusion is that this is MSFT's DLL and they'll do with it what they think is necessary. Look at applocal deployment to avoid this.

It's this just a question of which directory your configuration is set to build against. As long as you have all the versions of headers on your machine and the libraries they link against I don't see why this can't be a new configuration for each version.

If the issue is things like SP1, there's not much you can do. Microsoft considers the runtime, in effect, a component of the operating system. It therefore gets updates and patches the same as any OS component.
There shouldn't be a problem with this, normally - the patches are bugfixes and security updates after all. In principle, each change should make your apps more stable. Not quite always true, but in any case there isn't much you can do about it.
There are options to change the runtime, but they are related to thread-safety and similar issues. There's a few relevant places in the project properties. In particular, in the C/C++/Code Generation tab you can select which run-time library to use.
If you are seriously worried, you can choose a statically linked non-DLL runtime. Users can still update their runtime DLL, but it won't improve the stability of your app when they do so.

You can do this using manifest resource files, which are written in XML.
We had to do this at a previous place of employment, unfortunately (or perhaps, more fortunately), I was not exposed to the in depth details of how it was done. This article looks about the closest to what we did that I could find on the subject.
Update0
Here is MSDN documentation regarding manifest file generation, and their use in isolating applications and building side by side assemblies.

Related

Statically link with Microsoft CRT, and OpenMP

I’m developing some Windows software that's sometimes used in embedded-like scenarios. That’s not uncommon for my users to have a dedicated Win7 or Win8 PC they never update, not even connect to the Internet. Users plug those PC to a specific industrial hardware, and use that system for one job only.
My software includes components I've written in Visual C++. I include CRT in my MSI packages using appropriate installer merge modules.
Unfortunately, for a PC that never updated, that doesn’t work: today I got a bug report, the app crashes on startup saying “can’t start because api-ms-win-crt-stdio-l1-1-0.dll is missing from your computer”
This answer suggests static link to CRT.
Did that. But some parts of my C++ code rely on OpenMP for parallelism.
Dependency walker shows me the DLL I’m building depends on vcomp140.dll even when compiled with Multi-threaded (/MT) runtime library settings.
Also it shows vcomp140.dll only depends on kernel32.dll and user32.dll.
Can I just place that single DLL, vcomp140.dll, in the installation folder? Will it work on offline Windows 7 PC?
Based on the VS2015 Redistribution List I would say that copying that file would be indeed what you need to do and would work fine (if you used VS2015 to build your app). Take care to copy the proper dll based on arm/x86/x64.
Just to make it clear, it is not possible to statically link openmp with Visual Studio. Only two things you can do:
Remove openmp (and compile with /MT /MTd)
deploy vcomp140.dll (or VC redistributable) with your application

Are there any registry entries that indicate whether a specific C Run-Time is already installed?

I've been looking online and at my registry and I think not, but it would be nice if we could get a definitive answer on here.
Just the run time, as in for re-use on the client side.
I see it is possible for VC10, http://blogs.msdn.com/b/astebner/archive/2010/05/05/10008146.aspx, but prior to that we need to call the MsiQueryProductState API. Perhaps just give all the clients MSVCR100.DLL already?
The most common practice is to install the CRT your application was built with, regardless.
I think this practice comes from the v90 and lower CRTs, because there were multiple versions of each redistributable that could be installed, and though MSVCR90.DLL exists on the system, it may not be the version your application uses.
I believe this was changed with the v100 CRT, and now Microsoft guarantees that newer versions of the CRT will be usable in place of an older version, but I would still attempt to install the CRT your application was linked with.
It is still possible to do a private install of the Dll's into the application's folder. I recently installed 3 different version of the VC9 runtime when I was setting up my Visual Studio Express environments. All show up in Control Panel and appear to be readily removable.
For that reason I believe the current best practise to be to perform a private install (I think that is the terminolgy MS uses) of the required DLL's (for managed code you need the managed DLL and the native version) in tha app's folder.

Should I use vcredist.exe or the msm's to install the Visual C++ runtime library

What are the pluses and minuses to using the vcredist.exe versus the msm files to install the Visual C++ 8.0 runtime libraries?
Merge Modules can not be updated (unless they solved that in Windows Installer) once they are installed, so my advice would be to stick with vcredist.exe.
Another issue with the merge modules I recently bumped into is that they set the MSI installer property ALLUSERS to 1 which means per-machine. That forces your whole install to be per-machine, which is a problem if you want it to be per-user. Whether there's a way to have a per-user installer that includes a CRT merge module I don't know, but I haven't found it yet.
One downside to the merge modules is that you can't deploy multiple versions of the VC80 or VC90 merge module in the same msi because the file identifiers overlap. You can deploy one of each though. So for example, if you wanted to deploy the RTM version of VC80 and the SP1 version, you will get errors if they are in the same msi (I use WiX).
Another issue, build behavior is different between VS 2005/2008 as it pertains to applying a service pack or update.
2005
If you install service pack 1 on your build machine, your program will automatically link against the updated files. The service pack will also update the merge modules, so provided you're pointing your installer to use the updated files, you're fine. However, this can be an issue if you're using third party compiled static libs that may require an older version of the runtime specifically.
2008
The behavior here is the exact opposite. If you install SP1, the merge modules are updated to the SP1 level, but your program will compile against the RTM versions unless you set a per-project preprocessor macro: _BIND_TO_VCLIBS_CURRENT_VERSION=1. This can be set either in stdafx.h or in the "Preprossor definitions" for your project, or if you're using an old nmake project, you will have to pass it wherever your command line options are, such as CFLAGS.
This means that if you're using the msm provided by visual studio, and you apply SP1, your project deployment is broken until you define the macro.
Another caveat to the macro: if you're using a 2005 project that links against a 2008 static lib, setting the macro will break the 2005 project, due to the symbol not existing in the 2005 version of the compiler. In this case I usually split the project I'm linking against into a 2005 and 2008 version of the solution.
To point out the obvious, Merge Modules are not really a good solution if you aren't going to use an MSI installer. Vcredist is absurdly simple to use regardless of the install process you are using.
MSM will give you a better streamline experience then vcredist, it will integrate with the progress bar and will rollback on error (or cancel).
From the developer side you will benefit by seeing the msm log in the main setup log file and it will execute its actions side by side with the setup action (with vcredist you will need to sequence it yourself).
Because of all of the above reasons I usually choose to use the msm (and its more or less one Wix liner to use it).
Have you considered statically linking instead? Then you don't have a redistribution problem.

Does the latest Visual Studio 2005 Security Update cause C runtime library issues when hot fixing customer sites

As you might be aware an update to visual studio 2005 was auto updated on most machines last week. This update included a new version of the visual c runtime library. As a result any binaries built after the update also require a new redistributable installed on client systems.
See http://support.microsoft.com/kb/971090/
And here is the installer for the new redistributable:
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=766a6af7-ec73-40ff-b072-9112bab119c2
This is fine for distributing new binaries to customers, I will ship the new redistributable with the installer and it will all work.
However I am really worried about my ability to hotfix existing customer sites if they discover a bug. In this case normally I would just send the dll or exe that was fixed.
However if I do this now, I will have to send these customers the new redistributable and now I will be using two different versions of the c runtime library in the same executable.
Is this a problem?
Can this cause my application to crash?
What happens if I allocate memory in one dll then deallocate it in another? Normally this works if the same release runtime library is used. I went through the our code about 3 years ago cleaning this up, but I cannot be sure that I have found and fixed all occurrences.
Is the allocate/deallocate in different dlls still a problem? Now that in the era of smart pointers etc it is very had to enforce this.
Can I control what runtime library version I depend on by changing manifests?
Any pointers or advice would be grateful.
Updated: I have just noticed this question
VC++: KB971090 and selecting Visual C Runtime DLL dependencies This is very similar, but my question is more concerned with using two different version of the runtime in one executable.
The version number specified in the application’s manifest file/resource only specifies the minimum version required to run the application. The default behavior of the loader is to first check the WINDOWS\WinSxS folder for the identical version or a superseding version of a dependency identified in an application manifest, and to use that version regardless of whether or not a private assembly containing the dependency has been provided with the application. (See http://msdn.microsoft.com/en-us/library/aa375674(VS.85).aspx).
So chances are your old binaries will also use the latest version of the Microsoft run time library anyway. Try to run the release build of your application (built before you update your Visual Studio) on a fully patched machine and use process explorer to see which DLLs it loads. The only problem is you will have to include the new run time redistributable file in your patch.
If you are still worried, you can try the method described here: http://tedwvc.wordpress.com/2009/08/10/avoiding-problems-with-vc2005-sp1-security-update-kb971090/
Yes you will not have to wait too much to see the problems using two runtime libraries.
If you allocate memory with a runtime and try to release it with another, your application will crash. It is and will continue being a problem.
Only the runtime what reserved the memory can track it. It is imposible for the other runtime to know how much memory you reserved.
You may want to read this, is a really good post about linking with msvcrt.dll.
I have heard (only by rumour) that if the manifest gives two versions of the CRT that only differ by minor revision number, then the application ends up only using the newer version at runtime. Ie, you do not run into problems with with multiple CRTs.
This is only rumour, and I'd love to hear a concrete answer on this.
See also: Visual Studio 2005 security updates and CRT DLL versions in manifest

SidBySide: 3rd Party Dll refers to two versions of MSVCR80.DLL

We include a 3rd Party lib+DLL that recently causes a lot of trouble on installations. Using dependencywalker, we found that the dll itself refers to two different Versions of
MSVCR80.DLL:
Version 8.0.50727.4053 and
Version 8.0.50727.42
alt text http://img101.imageshack.us/img101/1734/dependencywalk2.jpg
In MOST cases installation makes no problems, even if we distribute none of both versions. But in a number of cases our installation just does not start. We then find messages in the windows system event log from the SideBySide manger: "Version of DLL does not match". In most cases again this problem can be resolved, by installing the .NET framework (although we do not use this). But now we have a case where this does not help.
I know that a solution would be, to install both versions as a shared assembly, but that seems not to be easy, and besides that i would prefer a much simpler solution. Does anybody know a workaround?
Can i somehow use only one version of the Dll?
EDIT:
I now tried cristians advice:
D:\Develop\LEADTOOLS15\patch_maifest>mt.exe -inputresource:ltkrn15u.dll;#1 -out:old.manifest
Microsoft (R) Manifest Tool version 5.2.3790.2075
Copyright (c) Microsoft Corporation 2005.
All rights reserved.
mt.exe : general error c101008c: Failed to read the manifest from the resource of file "ltkrn15u.dll". Ressource not found.
If i view the dlls dependencies with full paths, i see the following:
alt text http://img340.imageshack.us/img340/4122/dependencywalk3.jpg
The lower MSVCR80.DLL is the one withe Version ...42. I dont understand this. Why does MSVCP80.DLL refer to a different Version of MSVCR80.DLL than the one besides it. Is that maybe a problem of the dependencywalker ?
Your best option is to ship the needed DLLs within your applications installer package. Use at least the version that your 3rd party DLL depends on.
Microsoft offers standalone installers for its runtime DLLs (vcredits_*). The latest version for VisualStudio 2005 can be downloaded here. That is also the version that your DLL is linked against. You can silently launch the redistributable package from your installer.
As a manual workaround for already installed systems, simply apply the redist installer on the target machine.
If you choose this method, you don't need to be afraid of version conflicts, as applications depending on an older versions will be redirected to always use the most recent one.
For a better understanding you have look at this MSDN articles.
You have to change / update the manifest resource from the dlls.
mt.exe -inputresource:dll_with_manifest.dll;#1 -out:old.manifest
mt.exe -manifest new.manifest -outputresource:dll_with_manfiest.dll;#1
Sometimes the RT_MANIFEST (type 24) resource type doesn't have the #1 index in resource table, you should use a Resource Viewer (ResourceHacker, or ResEdit) and find out the index number. I have seen cases when the manifest has the #2 index number.