Thursday, July 24, 2008

Visual Studio 2008 C++ Redistributable Components

I've wasted two hours hunting down files that should be obvious, so I'm hoping this post helps someone else.

If you need to redistribute components from Visual Studio 2008, such as the C runtime or the MFC DLLs, there are four ways to do it:

1. Put the DLLs in your installer and install them into Windows\System32 directory yourself.

DON'T EVEN THINK OF DOING THIS. It's almost impossible to do it right because of WinSxS. If you want complete control over your installation, use option #2.

2. Use the redistributable directories Microsoft provides.

These directories provide copies of the DLLs that are only available to your application. The directories should go in the same install directory as your EXE. This means that they are subdirectories of wherever your EXE is installed. [Updated 11/19/2008] I no longer recommend copying the directory itself. Instead, copy the contents of the redistributable directory into the same directory as your app. Make sure you include the manifest file. I made this change because msvcm90.dll will not bind to msvcr90.dll if they are a subdirectory. As a bonus, this change makes this option work with Windows 2000.

Assuming you've installed Visual Studio 2008, you can find the directories at:

C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86

Important: If you do this with Visual Studio 2008 SP1, make sure you put the following in your precompiled header:

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1


Advantage: Doesn't require admin privileges. Works with XCOPY. Your app won't break if the system global version is updated by Microsoft (but you won't benefit from security fixes either.)
Disadvantage: Not viable if your EXEs and DLLs are installed across multiple directories.

3. Microsoft Visual C++ 2008 Redistributable Package:

Original distribution.

SP1 distribution. See caveats.

[Update 6/22/2009] Both of these distributions cause the the Windows 7 Logo Toolkit Beta to generate FAIL errors.

Advantage: All you have to do is run it. Permamently installs the components in the proper locations.
Disadvantage: Includes everything, so it's larger than the individual merge modules. If you are building your own installer, not as clean of a user experience as the merge modules.

4. Use the Merge Modules.

Assuming you've installed Visual Studio 2008, you can find the files at:

C:\Program Files\Common Files\Merge Modules

Advantage: Best user experience. Smallest download.
Disadvantage: Installation isn't permanent - the DLLs may be uninstalled when your application is uninstalled. Requires you to use Windows Installer. (This is only a disadvantage for a minority of developers. Windows Installer is a logo requirement for Vista.)

11 comments:

  1. Thanks Jim for showing:

    _BIND_TO_CURRENT_VCLIBS_VERSION

    Our company has been shipping our MFC app in VS 2003, 2005 and 2008 without any need to require the installation of the redistributable package.

    When SP1 came out for VS 2008 we came to a complete stand still. Now we are back to a simple deployment once again.

    -Tim

    ReplyDelete
  2. thanks a lot Jim.
    so, the best way is the second way. right?

    ReplyDelete
  3. There is no right or wrong way (except #1.) Solution numbers two through four each have situations where they are best.

    ReplyDelete
  4. I am using VS2008 SP1. I have an application where the main exe is standard windows exe without pre-compiled headers. It calls MFC dll's that have pre-compiled headers. When I use method 2 the program still does not initilize. If I run the vcredist_86 exe files than the application works fine. However, I do not want to have to deal with admin rights. Any idea why method 2 can be causing me grief?

    Thanks
    -Tom

    ReplyDelete
  5. There are four likely reasons:

    1. You didn't copy the manifest file that describes the DLLs.
    2. You didn't copy all of the dependent DLLs (use the DEPENDS utility to double check)
    3. You copied the wrong version of the libraries. (Open the EXE in resource mode and check the version in the manifest.)
    4. Your manifest contains conflicting version information, which is quite common if you are linking any LIB files.

    ReplyDelete
  6. what does "not viable" mean for option #2? if i have multiple dir's would i not just copy the files to each of my dirs?

    ReplyDelete
  7. greggT - In theory it's doable if every directory is completely mutually exclusive and there is absolutely no chance that executable content from one directory will ever be loaded into the executing address space of another directory. However, this arrangement is an incredibly bad idea and may indicate a significant design flaw in the application design. Either you should build statically linked EXEs or you should use either Option #3 or Option #4.

    For example, Microsoft Office puts Excel, Word, Outlook, and PowerPoint all in the same directory for exactly this reason.

    ReplyDelete
  8. >>Anonymous said...
    >>Any idea why method 2 can be causing me grief?
    May be you forgot about #define _BIND_TO_CURRENT_VCLIBS_VERSION in your application...
    My app didn't work until I add this define. You can read more about it here http://msdn.microsoft.com/en-us/library/cc664727.aspx

    ReplyDelete
  9. My application also worked fine after inserting #define _BIND_TO_CURRENT_VCLIBS_VERSION 1 at the beginning of stdafx.h

    ReplyDelete
  10. Hi Jim.

    I have made an c++ dll with VS2008 - redistributable package. In excel 2007 it works perfect, but in excel 2003 I get Run-time error 48 - "File not found". When I remove the dll-file, the error changes to error 53.
    Do you have any suggestion on how to solve this?

    - John

    ReplyDelete
  11. Anonymous,

    Unless there is a good reason to use the redistributable DLL, I'd definitely use static linking for a project like that. Otherwise you end up with multiple copies of the C-Runtime DLL loaded into Excel, which is not a good thing.

    ReplyDelete