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

33

有没有一个注册表设置可以确定 Visual C++ redistributable 是否已经安装,无论是独立安装还是作为 Visual Studio 2008 的一部分?我知道我可以启动 VC++ 2008 redistributable 安装程序并让它处理检测,但如果已经在系统上安装了 redistributable,如果我能够检查到并避免启动安装程序会更好。

如果没有要搜索的设置也没关系,因为这只是我们新软件版本的初步安装程序所需的。我们不需要它用于我们正在开发的基于 Windows Installer 的安装程序,这些安装程序将取代旧技术,并使用合并模块。

13个回答

19

我认为这些解决方案都不能在使用不同操作系统时提供帮助!例如,MsiQueryProductState将始终返回-1来使用Vista VC8.0。

而在Windows 7上,VC8.0 / 8.0 SP1 / 9.0的返回值为-1! 因此,Microsoft提供的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}

1
您可以在注册表的卸载键下检查这些内容。例如,在64位机器上的VC2008SP1 x86 = HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall{9A25302D-30C0-39D9-BD6F-21E6EC160475}。 - xt1
注意:对于那些可能会复制@xt1发布的注册表路径的人,它包含一个[零宽度不连字符](http://en.wikipedia.org/wiki/Zero-width_non-joiner)(‌)和一个[零宽度空格](http://en.wikipedia.org/wiki/Zero-width_space)(​),在路径的卸载部分需要将其删除。 - JG in SD

16

检查注册表:

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}

注:HKLM是指HKEY_LOCAL_MACHINE。

4
我发现这是一个错误的假设,因为同一版本(因此有不同的GUID)可能存在多个发布版本。 - lImbus
7
不要使用 GUID 来检查安装!在我的 XP 电脑上,我刚安装的 VC2008 SP1 redist 具有不同的 GUID。请注意,在翻译过程中,我已将原文中的"XP box" 翻译为 "XP 电脑",以更符合中文表达习惯。 - Ben M

6

非常感谢!我认为MFC安全更新的版本是8.0.61001。我是对的吗? - Martin Dimitrov
是的,DL页面显示:“已经发现了一个安全问题,由于MFC没有指定系统/本地化DLL的完整路径,导致DLL植入中的MFC应用程序漏洞。” - kenjiuno

5

简单粗暴:

if (LoadLibrary(L"msvcrt80.dll")!=NULL)
{
  // it is installed
}

Loadlibrary函数将为您处理路径搜索。


这种方法的一个问题是,您必须为要使用的每个DLL都执行此操作。其中一个的存在并不能保证其他任何DLL的存在;聪明的人可以通过调整注册表来“安装”其中一个DLL。 - RobH
6
这真聪明,不是吗?如果你问我,这似乎是一件愚蠢的事情。 - 1800 INFORMATION

5
看起来微软开发人员提出了另一个解决方案,使用MsiQueryProductState API,但也依赖于GUID。
更新:代码已经上线并且似乎运行良好。这里是正在进行的操作:检查已知的最新GUID和程序安装路径。如果两者都失败,则进行安装。这似乎很有效。
此外,它使用命令行参数"/qb"进行安装,意思是“无人参与但不可见”。有关这些参数,请参见此其他博客文章
对于Microsoft Visual C++ 2008 / VC90 SP1 Redistributable - x86 9.0.30729的GUID:
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*

2

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


这种方法的一个问题是,您必须为要使用的每个DLL都执行此操作。其中一个的存在并不能保证其他任何DLL的存在;聪明的人可以通过调整注册表来“安装”其中一个DLL。 - RobH
1
一个足够“聪明”的人可以欺骗你能想象到的任何测试 - 看起来试图超越那个人并不值得麻烦。 - 1800 INFORMATION
检查目录名称。这就是你需要的全部。DLL重新分发套件应该安装所有相关的DLL或者不安装任何一个。 - Gili
1
只有一件事,VS2008是VC90而不是vc80。 - gbjbaanb

2
我将一个检查VC++可再发行DLL的Visual C++项目在Github上开源,并以Apache 2.0许可证提供。它有三种不同的方法来检查VC++9和VC++10运行时的可用性:
1. 检查MsiQueryProductState API; 2. 检查WinSxS文件夹的内容以匹配产品目录;以及 3. 检查当前工作目录中是否有任何本地版本的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;

我将crt-detector项目授权为Apache 2.0许可,所以您可以放心在自己的应用程序中使用它。

1

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

1)如果您已安装Visual Studio,则所需的DLL将存在,但“redist package”不存在,因此注册表键丢失。(即这将给出错误的负面结果)。但是,在这种情况下在顶部安装redist是无害的。

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

3)如果您使用LoadLibrary或检查Dll文件,请确保针对正确的版本进行目标定位。如果您寻找“任何”副本的msvcrt80.dll(等),则无法确定它是否是与您的程序链接的版本。


1

“Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package MFC Security Update (x86)” 的产品代码为 {9BE518E6-ECC6-35A9-88E4-87755C07200F}。


0

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

它有效!

敬礼。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接