如何检测 VC++ 2008 可再发行组件?

Posted

技术标签:

【中文标题】如何检测 VC++ 2008 可再发行组件?【英文标题】:How to detect VC++ 2008 redistributable? 【发布时间】:2008-10-14 23:22:07 【问题描述】:

是否有我可以查找的注册表设置来确定是否安装了 Visual C++ 可再发行组件,无论是独立安装还是作为 Visual Studio 2008 的一部分安装?我知道我可以启动 VC++ 2008 可再发行安装程序并让它处理检测,但如果我可以检查它并且如果可再发行已在系统上,则无需费心启动安装程序,它看起来会更干净。

如果没有要搜索的设置,这没什么大不了的,因为这仅适用于我们为新版本软件提供的初步安装程序。我们正在开发的基于 Windows Installer 的新安装程序将不需要它,它将取代旧的技术安装程序并使用合并模块。

【问题讨论】:

【参考方案1】:

当您使用不同的操作系统时,我认为这些解决方案中的任何一个都无济于事!例如,使用 Vista VC8.0 时,MsiQueryProductState 将始终返回 -1

而 -1 用于 VC8.0/8.0 SP1/9.0 和 Windows 7 !所以微软提供的 GUID 解决方案并非在所有情况下都有效

所以我想我不得不坚持使用 %windir%\winsxs 方法并搜索

x86_Microsoft.VC80.CRT* x86_Microsoft.VC90.CRT*

对于那些正在寻找所有 GUID 的人,这是我创建的列表:

Visual C++ 2005 运行时文件

* VC 8.0 (x86) - A49F249F-0C91-497F-86DF-B2585E8E76B7
* VC 8.0 (x64) - 6E8E85E8-CE4B-4FF5-91F7-04999C9FAE6A
* VC 8.0 (ia64) - 03ED71EA-F531-4927-AABD-1C31BCE8E187

Visual C++ 2005 SP1 运行时文件

* VC 8.0 SP1 (x86) - 7299052B-02A4-4627-81F2-1818DA5D550D
* VC 8.0 SP1 (x64) - 071C9B48-7C32-4621-A0AC-3F809523288F
* VC 8.0 SP1 (ia64) - 0F8FB34E-675E-42ED-850B-29D98C2ECE08

Visual C++ 2005 SP1 ATL 安全更新运行时文件

* VC 8.0 SP1 ATL Patch (x86) - 837B34E3-7C30-493C-8F6A-2B0F04E2912C
* VC 8.0 SP1 ATL Patch (x64) - 6CE5BAE9-D3CA-4B99-891A-1DC6C118A5FC
* VC 8.0 SP1 ATL Patch (ia64) - 85025851-A784-46D8-950D-05CB3CA43A13

Visual C++ 2008 运行时文件

* VC 9.0 (x86) - FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4
* VC 9.0 (x64) - 350AA351-21FA-3270-8B7A-835434E766AD
* VC 9.0 (ia64) - 2B547B43-DB50-3139-9EBE-37D419E0F5FA 

Visual C++ 2008 SP1 运行时文件

* VC 9.0 SP1 (x86) - 9A25302D-30C0-39D9-BD6F-21E6EC160475
* VC 9.0 SP1 (x64) - 8220EEFE-38CD-377E-8595-13398D740ACE
* VC 9.0 SP1 (ia64) - 5827ECE1-AEB0-328E-B813-6FC68622C1F9

Visual C++ 2008 SP1 ATL 安全更新运行时文件

* VC 9.0 SP1 ATL (x86) - 1F1C2DFC-2D24-3E06-BCB8-725134ADF989
* VC 9.0 SP1 ATL (x64) - 4B6C7001-C7D6-3710-913E-5BC23FCE91E6
* VC 9.0 SP1 ATL (ia64) - 977AD349-C2A8-39DD-9273-285C08987C7B

【讨论】:

您可以在注册表中的 Uninstall 项下检查这些内容。例如 64 位机器上的 VC2008SP1 x86 = HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\9A25302D-30C0-39D9-BD6F-21E6EC160475 注意那些可能将路径复制到@xt1 发布的注册表路径的人,它在卸载中包含一个Zero-width non-joiner (‌) 和一个Zero-width space (​)路径的一部分,需要删除。【参考方案2】:

检查注册表:

VC++2008 (sp1): HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\3C3D696B-0DB7-3C6D-A356-3DB8CE541918

VC++2008(原创): HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4

【讨论】:

我发现这是一个错误的假设,因为这样的版本有不同的版本(以及 GUID)。 不要使用指导来检查安装!在我的 XP 机器上,我刚安装的 VC2008 SP1 redist 的 guid 与列出的不同。【参考方案3】:

VC2005的最新版本:

Visual C++ 2005 Service Pack 1 可再发行包 MFC 安全更新

* VC 8.0 SP1 MFCLOC Patch (x86) - 710F4C1C-CC18-4C49-8CBF-51240C89A1A2
* VC 8.0 SP1 MFCLOC Patch (x64) - AD8A2FA1-06E7-4B0D-927D-6E54B3D31028
* VC 8.0 SP1 MFCLOC Patch (ia64) - C2F60BDA-462A-4A72-8E4D-CA431A56E9EA

8.0.50727.6195

http://www.microsoft.com/downloads/details.aspx?familyid=AE2E1A40-7B45-4FE9-A20F-2ED2923ACA62

【讨论】:

非常感谢!我认为 MFC 安全更新的版本是 8.0.61001。我说的对吗? 是的,DL 页面显示“由于 MFC 未指定系统/本地化 DLL 的完整路径,已发现一个安全问题导致 MFC 应用程序在 DLL 植入中存在漏洞”。【参考方案4】:

又快又脏:

if (LoadLibrary(L"msvcrt80.dll")!=NULL)

  // it is installed

Loadlibrary 将为您处理搜索路径。

【讨论】:

这种方法的一个问题是您必须为每个要使用的 DLL 执行此操作。一个人的存在并不能保证其他任何人的存在;一个足够聪明的人可以欺骗注册表来“安装”其中一个 DLL。 那会很聪明吧?如果你问我,这似乎是一件愚蠢的事情【参考方案5】:

看起来微软开发人员提出了another solution,使用MsiQueryProductState API,可惜也依赖于GUID。

更新:代码昨天上线,似乎工作正常。以下是正在做的事情:检查我最新知道的 GUID 和路径² to-where-it-is-supposed-to-be-installed。如果两者都失败,则安装它。这似乎工作正常。

此外,它使用命令行参数“/qb”安装,意思是“无人看管但不是不可见”。有关这些参数,请参阅 this other blog post。

FWIW,Microsoft Visual C++ 2008 / VC90 SP1 可再发行组件的 GUID - x86 9.0.30729

64 位 30729.17: 8220EEFE-38CD-377E-8595-13398D740ACE 32 位 30729.17: 9A25302D-30C0-39D9-BD6F-21E6EC160475 32 位 30729.01: 6AFCA4E1-9B78-3640-8F72-A7BF33448200

² 路径: $WINDIR\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729*

【讨论】:

【参考方案6】:

例如,如果您正在检查 Visual Studio 2008 可再发行组件,请检查 $WINDIR\WinSxS\x86_Microsoft.VC90.CRT_*

【讨论】:

这种方法的一个问题是您必须为每个要使用的 DLL 执行此操作。一个人的存在并不能保证其他任何人的存在;一个足够聪明的人可以欺骗注册表来“安装”其中一个 DLL。 一个足够“聪明”的人可以伪造任何你能想象到的测试 - 试图超越这一点似乎真的不值得麻烦 检查目录名称。这就是你所需要的。 DLL 再分发套件应该安装所有相关的 DLL,或者根本不安装。 只有一件事,VS2008 是 VC90 而不是 vc80。【参考方案7】:

我专门开源了a Visual C++ project on Github that checks for VC++ redistributable DLLs,并在 Apache 2.0 许可下提供了它。

它具有三种不同的方法来检查 VC++9 和 VC++10 运行时的可用性:

    检查 MsiQueryProductState API; 检查 WinSxS 文件夹的内容是否匹配产品目录;和 检查当前工作目录以查找任何本地版本的 VC++9 和 VC++10 运行时(并检查其内容。)

编辑:以下是使用它的实际样子的示例:

 wcout << _T("Checking for the availability of VC++ runtimes..") << endl;
 wcout << _T("----------- Visual C++ 2008 (VC++9) -----------") << endl;
 wcout << _T("Visual C++ 2008 (x86) ? ") << (IsVC2008Installed_x86() ? _T("true") : _T("false")) << endl;
 wcout << _T("Visual C++ 2008 (x64) ? ") << (IsVC2008Installed_x64() ? _T("true") : _T("false")) << endl;
 wcout << _T("Visual C++ 2008 SP1 (x86) ? ") << (IsVC2008SP1Installed_x86() ? _T("true") : _T("false")) << endl;
 wcout << _T("Visual C++ 2008 SP1 (x64) ? ") << (IsVC2008SP1Installed_x64() ? _T("true") : _T("false")) << endl;

我在 Apache 2.0 下授权了 crt-detector 项目,因此请随意在您自己的应用程序中使用它。

【讨论】:

【参考方案8】:

更新其他遇到此问题的人:

1) 如果您安装了 Visual Studio,则将存在所需的 DLL,但“redist 包”不存在,因此缺少注册表项。 (即这将给出假阴性)。但是,在这种情况下将 redist 安装在顶部是无害的。

2) redist 的每个主要版本(VS2005/VS2008、x86/x64/IA64 和服务包的任意组合:SP1、ATL 安全更新)都有不同的 GUID。如果您希望在 x86 和 x64 PC 上部署您的应用程序,请小心。

3) 如果您使用 LoadLibrary 或检查 Dll 文件,请确保您使用正确的版本。如果您查找 msvcrt80.dll(等)的“任何”副本,那么您将无法判断它是否是您的程序链接到的版本。

【讨论】:

【参考方案9】:

“Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package MFC 安全更新 (x86)”的产品代码是 9BE518E6-ECC6-35A9-88E4-87755C07200F

【讨论】:

【参考方案10】:

您可以检查 WINDOWS\WinSxS 目录下的文件以查看您安装了哪些版本。通常可以一次安装多个版本,因此您可能需要检查已安装的特定版本。

【讨论】:

【参考方案11】:

我想用以下值扩展 GUID 列表:

32 位 30729.17 9A25302D-30C0-39D9-BD6F-21E6EC160475 32位30729.01 6AFCA4E1-9B78-3640-8F72-A7BF33448200 64位 30729.17 8220EEFE-38CD-377E-8595-13398D740ACE 64位30729.01 0DF3AE91-E533-3960-8516-B23737F8B7A2 VC++2008 (sp1) 3C3D696B-0DB7-3C6D-A356-3DB8CE541918 VC++2008(原创) FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4 IA64 30729.01 22E23C71-C27A-3F30-8849-BB6129E50679 32位 30729.4148 7B33F480-496D-334A-BAC2-205DEC0CBC2D Visual Studio 2008 专业版 SP1 D7DAD1E4-45F4-3B2B-899A-EA728167EC4F 32位30729.01 F333A33D-125C-32A2-8DCE-5C5D14231E27

所以请决定,通过 GUID 检查是否存在 VCredist 是否是个好主意。

【讨论】:

【参考方案12】:

最可靠的方法是使用带有不同 vcredist 版本的 GUID 的 MsiQueryProductState API。

有效!

问候。

【讨论】:

【参考方案13】:

找到 VC2008 可再发行组件的注册表项。这是我的解决方案:

BOOL IsVC2008RedistInstalled(LPCTSTR pLogFile)

    TCHAR szLogEntry[256];
    memset(szLogEntry, '0', sizeof(szLogEntry));
    HKEY hKey;
    LONG lErr;

    TCHAR csid[256];
    _stprintf( csid, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\9A25302D-30C0-39D9-BD6F-21E6EC160475"));
    lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, csid, 0, KEY_QUERY_VALUE, &hKey);
    if (lErr == ERROR_SUCCESS)
    
    _stprintf(szLogEntry, _T("VC2008 Redistributable was installed before.\n"));
    toFile(pLogFile, szLogEntry);
    return TRUE;
    
    else
    
    _stprintf(szLogEntry, _T("VC2008 Redistributable was not installed before. %ld\n"), lErr);
    toFile(pLogFile, szLogEntry);
    return FALSE;
    

【讨论】:

以上是关于如何检测 VC++ 2008 可再发行组件?的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft VC++ 2005 SP1 和 2008 SP1 可再发行包

VC_可再发行组件包

为 ClickOnce 先决条件指定 VC++ Redistributable 版本

如何包含 CEFSharp 所需的 VC++ 可再发行文件

如何在安装 WiX Bundle 时避免卸载以前安装的 ExePackage(可再发行文件)?

MySql 5.7 安装程序无法检测到 VS 2013 可再发行组件