如何检测 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 可再发行包
为 ClickOnce 先决条件指定 VC++ Redistributable 版本