25

I have a c++ application developed using Visual Studio 2015, along with a Wix installer and a Burn bootstrapper. Previous versions of the application were able to use the Visual Studio merge module to install the necessary prerequisites, but it appears that this isn't an option when using Visual Studio 2015 (see Redistributables for deploying C++ exe developed with Visual Studio 2015 on Windows 7).

Following the advice in that link, we have started installing vcredist with Burn using an ExePackage with vital="yes". This mostly works great - we've had several customers who have the installation fail because of various issues with vcredist. Until recently, these were errors that should cause the installation to fail.

In the past couple of days we've received several reports of our installer failing due to a newer version of the redistributable being installed: vcredist fails with error code 0x80070666, which causes our bootstrapper to fail.

My questions are:

  1. Is deploying vcredist the "correct" approach to take? (Assuming we need to have a single exe installer)
  2. How can we tell what version of the redistributables are installed (not necessarily in the bootstrapper, is this information stored in a user readable form somewhere)?
  3. Is there a newer version of the redistributables that we should be distributing? (Currently using 14.0.23026) Is this based on the version of Visual Studio that is being used to compile or should we always distribute the latest version? (Current VS version 14.0.23107.0)
  4. As a last resort, is it possible to detect the error code returned from vcredist and allow that value to determine if the installation continues or fails?
Community
  • 1
  • 1
Runt8
  • 547
  • 1
  • 7
  • 17

2 Answers2

39
  1. Deploying vcredist is an appropriate approach to take.

  2. You can use the FileSearch Element (Util Extension) to search for one of the vcredist files and retrieve its version. However this approach is complicated by the fact the burn built in variables SystemFolder and System64Folder are reversed with respect the similar variables in Windows Installer. Example of searches for VC14:

    <!-- Detect existing version of VC ++ 2015 x64 libraries -->
    <util:FileSearch Id="GetVC14X64Exists" Condition="VersionNT64" Variable="vc14x64Exists" Path="[SystemFolder]vcruntime140.dll" Result="exists"/>
    <util:FileSearch Id="GetVC14X64Version" Condition="VersionNT64" Variable="vc14x64Version" Path="[SystemFolder]vcruntime140.dll" Result="version"/>
    
    <!-- Detect existing version of VC ++ 2015 x86 libraries -->
    <util:FileSearch Id="GetVC14X86onX64Exists" Condition="VersionNT64" Variable="vc14x86Exists" Path="[System64Folder]vcruntime140.dll" Result="exists"/>
    <util:FileSearch Id="GetVC14X86onX64Version" Condition="VersionNT64" Variable="vc14x86Version" Path="[System64Folder]vcruntime140.dll" Result="version"/>
    <util:FileSearch Id="GetVC14X86onX86Exists" Condition="NOT VersionNT64" Variable="vc14x86Exists" Path="[SystemFolder]vcruntime140.dll" Result="exists"/>
    <util:FileSearch Id="GetVC14X86onX86Version" Condition="NOT VersionNT64" Variable="vc14x86Version" Path="[SystemFolder]vcruntime140.dll" Result="version"/>
    

    The variables vc14x64Exists and vc14x64Version can then be used in a DetectCondition to work out whether the 64 bit version of VC14 is installed:

    DetectCondition="vc14x64Exists AND vc14x64Version &gt;= v14.0.nnnnn"
    

    Similarly the DetectCondition for the 32 bit version of VC14 is:

    DetectCondition="vc14x86Exists AND vc14x86Version &gt;= v14.0.nnnnn"
    

    Note: In both cases you need to substitute nnnnn with the build number of the vcredist you are including in your installer.

    Edit 1: As an alternative you could detect the presence of VC Redist using an upgrade code search as outlined here.

    Edit 2: In the installers that I author I generally don't try to detect the presence of VC Redist. Instead I let the VC Redist installer run and let itself figure out whether to install, upgrade or do nothing.

  3. To date I've found three versions of the VC14 redist files:

    a) 14.0.23026 - Downloadable from Microsoft's link here.

    b) 14.0.23506 - Provided with Visual Studio 2015 Update 1.

    c) 14.0.23918 - provided with Visual Studio 2015 Update 2.

    Although newer versions of vcredist have been released with Visual Studio updates, Microsoft has not updated the version downloadable from their web site.

  4. You can tell burn to ignore the already installed error code 0x80070666 using <ExitCode Value="1638" Behavior="success"/>. Note that 1638 = 0x666. For example:

    <!-- Microsoft Visual C++ 2015 x86 libraries -->
    <PackageGroup Id="VC14RedistX86">
      <ExePackage
         Cache="no"
         Compressed="yes"
         PerMachine="yes"
         Permanent="yes"
         Vital="yes"
         Name="Redist\vcredist14_x86.exe"
         SourceFile="$(var.RedistPath)\VC14\vcredist_23918_x86.exe"
         InstallCommand="/install /quiet /norestart">
    
         <!-- -->
         <ExitCode Value="3010" Behavior="forceReboot"/>
    
         <!-- Ignore "Newer version installed" error -->
         <ExitCode Value="1638" Behavior="success"/>
      </ExePackage>
    </PackageGroup>
    

I ran into a similar problem recently where a product installer I was working on halted with error 0x80070666. The problem was a newer version of vcredist already installed. The solution I ended up using was: a) include the latest version of vcredist (14.0.23918), and b) add the <ExitCode Value="1638" Behavior="success"/> directive to tell burn not to throw an error if a future newer version of vcredist is already installed.

Community
  • 1
  • 1
bradfordrg
  • 1,863
  • 2
  • 21
  • 34
  • Awesome answer! To clarify - our informal testing so far hasn't run across any problems using a new version of the redistributables against an executable compiled against an older version (i.e., we haven't upgraded to Visual Studio 2015 update 1 or 2). Is this guaranteed to be the case or do we need to upgrade Visual Studio before we start shipping the newer redistributables? – Runt8 May 24 '16 at 15:41
  • 1
    In my testing I didn't find any issues running a product built with an older version of vcredist on a computer with a newer version of vcredist already installed. However there is no guarantee that a future release of vcredist won't break something. I tend to go with the latest release of vcredist on the assumption the latest version has the most up to date bug and security fixes etc. – bradfordrg May 24 '16 at 16:38
  • is there a registry key that can be read to determine what version is currently installed and use that as an installcondition for the exepackage? "InstallCondition" http://wixtoolset.org/documentation/manual/v3/xsd/wix/exepackage.html – tollgen May 25 '16 at 15:09
  • @tollgen - I'm not aware of a registry key that can be easily read to detect the presence of the exepackage. I've updated my answer with specific details on how a FileSearch might work. – bradfordrg May 26 '16 at 06:43
  • always returns false for me (c:\windows\system32\vcruntime140.dll not found), even when the package is installed. The install still looks fine, possibly because when it launches the VSRedist installer, it detects that it is already installed I noticed it when I canceled the install and checked the logs. For now, I just use the version number in the detect condition. That works fine and the install goes faster. – Daniel Aug 12 '16 at 20:13
  • 1
    Excellent to get to know about the ExitCode attribute, just what I needed! But there actually is a registry key you can you to look for installed VCRedist version: I use on my x64 installation (and similar for "minor" and "build" version numbers. – Torbjörn Bergstedt Oct 31 '16 at 05:24
  • Thanks for this answer, and I have one more question: If we must use Burn to do so, is that means we can only deploy Apps into a .exe file? How can we burn the vcredist into a MSI so that our customers can deploy the MSI to there network of computers? – Bill Hoo Apr 28 '18 at 08:57
  • @BillHoo You don't have to use Burn. A product called AdvancedInstaller describes how to package an MSI and vcredist in another MSI (see final entry of https://www.advancedinstaller.com/forums/viewtopic.php?t=29284). I've not used this product myself. – bradfordrg May 04 '18 at 05:42
  • @bradfordrg Thanks, I'm using WiX in our CD pipelines and not gonna change the toolchains. So the only way left for me seems to use Burn and make a .exe installer right? Maybe I should Googling about how to deploy .exe files with Windows AD domain. – Bill Hoo May 07 '18 at 08:21
  • To get the redistributable to report progress to your Burn bootstrapper, use chainingpackage like `/quiet /norestart /install /ChainingPackage "[WixBundleName]"` and take advantage of `Protocol="netfx4"`. – RMart Nov 26 '19 at 16:27
  • I have a comment/question about "Edit 2": When I run my WiX bootstrapper which includes the VC++ Redistributable (14.32.31326) (as an ExePackage) and a newer or the same version of VC++ Redistributable is already installed on the machine the user will get to see the VC++ installer window with "Repair", "Uninstall" and "Close" where pressing Close cancels the entire bootstrapper installation. Did you have the same issue and if so how did you overcome this? – Joey Muiser Jun 01 '22 at 18:34
  • The ExePackage attribute InstallCommand="/install /quiet /norestart" *should* prevent the VC++ Redistributable from opening a dialog. – bradfordrg Jun 02 '22 at 19:36
3

to detect the presence of a vcredist package you need to search by its UpgradeCode.
this will make sure that also later versions are found.

in a wix burn bootstrapper use util:ProductSearch with the UpgradeCodeparameter. and then specify a minimum version in the DetectCondition.

for full details see this answer of mine: https://stackoverflow.com/a/35889484

Opmet
  • 1,754
  • 18
  • 20
  • Current versions are deployed via burn bundles. They do have a different bundle id. This cannot be looked up with `util:ProductSearch` at the moment – Stephen Reindl Feb 10 '18 at 17:17