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

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

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

【问题讨论】:

    标签: visual-c++ redistributable


    【解决方案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 运行时的可用性:

      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;
      

      我在 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;
                      }
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-07-12
                    • 1970-01-01
                    相关资源
                    最近更新 更多