【问题标题】:How to make vcredist_x86 reinstall only if not yet installed?如何仅在尚未安装的情况下重新安装 vcredist_x86?
【发布时间】:2012-06-23 15:27:50
【问题描述】:

在我的 inno setup RUN 选择中,我强制静默安装 MSVCRT。我想知道如何让它在尚未安装的情况下自行安装?

这就是我现在所说的:

Filename: {tmp}\vcredist_x86.exe; Parameters: "/passive /Q:a /c:""msiexec /qb /i vcredist.msi"" "; StatusMsg: Installing 2010 RunTime...

【问题讨论】:

  • 有人问过类似的问题here 但是我不同意这个答案,因为它会在向导启动时安装框架,但是 IMO 它应该在您按下最后一个 Next 时运行 按钮,安装开始。我将尝试查找此检查所需的注册表项。同时看看this post。您需要为此使用Check 参数。

标签: inno-setup msvcrt


【解决方案1】:

由于您不想告诉您需要什么最小版本的 Visual C++ 可再发行程序包,这里有代码示例,您可以根据它自己构建它。请注意,我不知道,什么版本与什么兼容,必须安装什么低版本,我会一直告诉你的。

我唯一可以告诉你的是,你绝对应该使用Check 条件参数,在打开向导时尝试安装框架或运行时库的解决方案是错误的。此条件参数的工作方式与您返回 True 时一样,正在安装文件,如果为 False,则跳过它。因此,当您想要安装运行时库时,您需要将 True 返回到 VCRedistNeedsInstall 函数,否则返回 False。此处使用以VC_ 开头的常量的辅助函数VCVersionInstalled 在安装包时返回True,否则返回False。

作为本文的来源,我使用了以下来源:

  1. How to detect the presence of the VC 8.0 runtime redistributable package
  2. How to detect the presence of the VC 9.0 runtime redistributable package
  3. How to detect the presence of the VC 2010 runtime redistributable package

感谢kobik's idea to use the conditional define,以下代码应该与 Unicode 和 ANSI 版本的 Inno Setup 兼容。

代码如下:

[Files]
Source: "vcredist_x86.exe"; DestDir: {tmp}; Flags: deleteafterinstall

[Run]
; add the Parameters, WorkingDir and StatusMsg as you wish, just keep here
; the conditional installation Check
Filename: "{tmp}\vcredist_x86.exe"; Check: VCRedistNeedsInstall

[Code]
#IFDEF UNICODE
  #DEFINE AW "W"
#ELSE
  #DEFINE AW "A"
#ENDIF
type
  INSTALLSTATE = Longint;
const
  INSTALLSTATE_INVALIDARG = -2;  { An invalid parameter was passed to the function. }
  INSTALLSTATE_UNKNOWN = -1;     { The product is neither advertised or installed. }
  INSTALLSTATE_ADVERTISED = 1;   { The product is advertised but not installed. }
  INSTALLSTATE_ABSENT = 2;       { The product is installed for a different user. }
  INSTALLSTATE_DEFAULT = 5;      { The product is installed for the current user. }

  VC_2005_REDIST_X86 = '{A49F249F-0C91-497F-86DF-B2585E8E76B7}';
  VC_2005_REDIST_X64 = '{6E8E85E8-CE4B-4FF5-91F7-04999C9FAE6A}';
  VC_2005_REDIST_IA64 = '{03ED71EA-F531-4927-AABD-1C31BCE8E187}';
  VC_2005_SP1_REDIST_X86 = '{7299052B-02A4-4627-81F2-1818DA5D550D}';
  VC_2005_SP1_REDIST_X64 = '{071C9B48-7C32-4621-A0AC-3F809523288F}';
  VC_2005_SP1_REDIST_IA64 = '{0F8FB34E-675E-42ED-850B-29D98C2ECE08}';
  VC_2005_SP1_ATL_SEC_UPD_REDIST_X86 = '{837B34E3-7C30-493C-8F6A-2B0F04E2912C}';
  VC_2005_SP1_ATL_SEC_UPD_REDIST_X64 = '{6CE5BAE9-D3CA-4B99-891A-1DC6C118A5FC}';
  VC_2005_SP1_ATL_SEC_UPD_REDIST_IA64 = '{85025851-A784-46D8-950D-05CB3CA43A13}';

  VC_2008_REDIST_X86 = '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}';
  VC_2008_REDIST_X64 = '{350AA351-21FA-3270-8B7A-835434E766AD}';
  VC_2008_REDIST_IA64 = '{2B547B43-DB50-3139-9EBE-37D419E0F5FA}';
  VC_2008_SP1_REDIST_X86 = '{9A25302D-30C0-39D9-BD6F-21E6EC160475}';
  VC_2008_SP1_REDIST_X64 = '{8220EEFE-38CD-377E-8595-13398D740ACE}';
  VC_2008_SP1_REDIST_IA64 = '{5827ECE1-AEB0-328E-B813-6FC68622C1F9}';
  VC_2008_SP1_ATL_SEC_UPD_REDIST_X86 = '{1F1C2DFC-2D24-3E06-BCB8-725134ADF989}';
  VC_2008_SP1_ATL_SEC_UPD_REDIST_X64 = '{4B6C7001-C7D6-3710-913E-5BC23FCE91E6}';
  VC_2008_SP1_ATL_SEC_UPD_REDIST_IA64 = '{977AD349-C2A8-39DD-9273-285C08987C7B}';
  VC_2008_SP1_MFC_SEC_UPD_REDIST_X86 = '{9BE518E6-ECC6-35A9-88E4-87755C07200F}';
  VC_2008_SP1_MFC_SEC_UPD_REDIST_X64 = '{5FCE6D76-F5DC-37AB-B2B8-22AB8CEDB1D4}';
  VC_2008_SP1_MFC_SEC_UPD_REDIST_IA64 = '{515643D1-4E9E-342F-A75A-D1F16448DC04}';

  VC_2010_REDIST_X86 = '{196BB40D-1578-3D01-B289-BEFC77A11A1E}';
  VC_2010_REDIST_X64 = '{DA5E371C-6333-3D8A-93A4-6FD5B20BCC6E}';
  VC_2010_REDIST_IA64 = '{C1A35166-4301-38E9-BA67-02823AD72A1B}';
  VC_2010_SP1_REDIST_X86 = '{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}';
  VC_2010_SP1_REDIST_X64 = '{1D8E6291-B0D5-35EC-8441-6616F567A0F7}';
  VC_2010_SP1_REDIST_IA64 = '{88C73C1C-2DE5-3B01-AFB8-B46EF4AB41CD}';

  { Microsoft Visual C++ 2012 x86 Minimum Runtime - 11.0.61030.0 (Update 4) }
  VC_2012_REDIST_MIN_UPD4_X86 = '{BD95A8CD-1D9F-35AD-981A-3E7925026EBB}';
  VC_2012_REDIST_MIN_UPD4_X64 = '{CF2BEA3C-26EA-32F8-AA9B-331F7E34BA97}';
  { Microsoft Visual C++ 2012 x86 Additional Runtime - 11.0.61030.0 (Update 4)  }
  VC_2012_REDIST_ADD_UPD4_X86 = '{B175520C-86A2-35A7-8619-86DC379688B9}';
  VC_2012_REDIST_ADD_UPD4_X64 = '{37B8F9C7-03FB-3253-8781-2517C99D7C00}';

  { Visual C++ 2013 Redistributable 12.0.21005 }
  VC_2013_REDIST_X86_MIN = '{13A4EE12-23EA-3371-91EE-EFB36DDFFF3E}';
  VC_2013_REDIST_X64_MIN = '{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}';

  VC_2013_REDIST_X86_ADD = '{F8CFEB22-A2E7-3971-9EDA-4B11EDEFC185}';
  VC_2013_REDIST_X64_ADD = '{929FBD26-9020-399B-9A7A-751D61F0B942}';

  { Visual C++ 2015 Redistributable 14.0.23026 }
  VC_2015_REDIST_X86_MIN = '{A2563E55-3BEC-3828-8D67-E5E8B9E8B675}';
  VC_2015_REDIST_X64_MIN = '{0D3E9E15-DE7A-300B-96F1-B4AF12B96488}';

  VC_2015_REDIST_X86_ADD = '{BE960C1C-7BAD-3DE6-8B1A-2616FE532845}';
  VC_2015_REDIST_X64_ADD = '{BC958BD2-5DAC-3862-BB1A-C1BE0790438D}';

  { Visual C++ 2015 Redistributable 14.0.24210 }
  VC_2015_REDIST_X86 = '{8FD71E98-EE44-3844-9DAD-9CB0BBBC603C}';
  VC_2015_REDIST_X64 = '{C0B2C673-ECAA-372D-94E5-E89440D087AD}';

function MsiQueryProductState(szProduct: string): INSTALLSTATE; 
  external 'MsiQueryProductState{#AW}@msi.dll stdcall';

function VCVersionInstalled(const ProductID: string): Boolean;
begin
  Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

function VCRedistNeedsInstall: Boolean;
begin
  { here the Result must be True when you need to install your VCRedist }
  { or False when you don't need to, so now it's upon you how you build }
  { this statement, the following won't install your VC redist only when }
  { the Visual C++ 2010 Redist (x86) and Visual C++ 2010 SP1 Redist(x86) }
  { are installed for the current user }
  Result := not (VCVersionInstalled(VC_2010_REDIST_X86) and 
    VCVersionInstalled(VC_2010_SP1_REDIST_X86));
end;

更新chuckleplant

添加了 VC++ 2012 产品代码。请注意,可再发行包安装了两个东西,最小运行时和附加运行时。寻找最小运行时间应该就足够了。针对 Microsoft Visual C++ 2012 Redistributable 产品代码进行测试将给出 INSTALLSTATE_UNKNOWN,请改用最小运行时代码。 VC++ 2013 和 2015 也是同样的情况。

您可以在 HKEY_CLASSES_ROOT\Installer\Dependencies\ 中找到其他 Visual Studio 版本的产品代码,例如 HKEY_CLASSES_ROOT\Installer\Dependencies\Microsoft.VS.VC_RuntimeAdditionalVSU_amd64,v14

【讨论】:

  • 非常感谢您这么认真的回答!
  • 请注意,有时即使操作系统包含“VC++ 运行时”,它也不足以满足您的应用程序;有时会在您的开发 PC 上安装服务包或修补程序,最终需要比操作系统最初附带的更高版本的运行时。因此,在您的开发/构建 PC 上安装更新后,不要忘记始终在“干净”的 PC/VM 上测试您的应用。
  • @TLama 你愿意更新你对 VC_REDIST_2012 (microsoft.com/de-de/download/details.aspx?id=30679) 的答案吗?我认为 regkey 是“{8e70e4e1-06d7-470b-9f74-a51bef21088e}”。未经测试。
  • MS 有官方方法可以通过检查HKEY_LOCAL_MACHINE\SOFTWARE[\Wow6432Node]\Microsoft\DevDiv\vc\Servicing\14.0\RuntimeMinimum 来检测是否安装了VC++:msdn.microsoft.com/en-us/library/…
  • 以防万一有人想要 VC++ 2017 的 GUID // Visual C++ 2017 Redistributable 14.10.25 VC_2017_REDIST_X86_MIN = '{029DA848-1A80-34D3-BFC1-A6447BFC8E7F}'; VC_2017_REDIST_X64_MIN = '{8D50D8C6-1E3D-3BAB-B2B7-A5399EA1EBD1}'; VC_2017_REDIST_X86_ADD = '{568CD07E-0824-3EEB-AEC1-8FD51F3C85CF}'; VC_2017_REDIST_X64_ADD = '{C668F044-4825-330D-8F9F-3CBFC9F2AB89}';
【解决方案2】:

这是一个版本,它使用 Microsoft 推荐的方法来确定是否安装了 VC Redistributable。我只需要 VC 2015,因此您需要为其他版本调整值和参数​​:

[Files]
Source: ".\vc-redist\vc-redist\win64\bin\vc_redist.x64.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall; Check: Is64BitInstallMode

; FlexLM requires the VC 2015 redistributables so run the installer if this 
; or a later 2015 version is not already present
[Run]
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /passive"; StatusMsg: "{#VCmsg}"; Check: IsWin64 and not VCinstalled

[Code]
function VCinstalled: Boolean;
 // Function for Inno Setup Compiler
 // Returns True if same or later Microsoft Visual C++ 2015 Redistributable is installed, otherwise False.
 var
  major: Cardinal;
  minor: Cardinal;
  bld: Cardinal;
  rbld: Cardinal;
  key: String;
 begin
  Result := False;
  key := 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64';
  if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'Major', major) then begin
    if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'Minor', minor) then begin
      if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'Bld', bld) then begin
        if RegQueryDWordValue(HKEY_LOCAL_MACHINE, key, 'RBld', rbld) then begin
            Log('VC 2015 Redist Major is: ' + IntToStr(major) + ' Minor is: ' + IntToStr(minor) + ' Bld is: ' + IntToStr(bld) + ' Rbld is: ' + IntToStr(rbld));
            // Version info was found. Return true if later or equal to our 14.0.24212.00 redistributable
            // Note brackets required because of weird operator precendence
            Result := (major >= 14) and (minor >= 0) and (bld >= 24212) and (rbld >= 0)
        end;
      end;
    end;
  end;
 end;

【讨论】:

    【解决方案3】:

    容易多了:

    #define VCmsg "Installing Microsoft Visual C++ Redistributable...."
    
    [Run]
    Filename: "vc_redist.x86.exe"; StatusMsg: "{#VCmsg}"; Check: not IsWin64 and not VCinstalled
    Filename: "vc_redist.x64.exe"; StatusMsg: "{#VCmsg}"; Check: IsWin64 and not VCinstalled
    
    [Code]
    function VCinstalled: Boolean;
     // By Michael Weiner <mailto:spam@cogit.net>
     // Function for Inno Setup Compiler
     // 13 November 2015
     // Returns True if Microsoft Visual C++ Redistributable is installed, otherwise False.
     // The programmer may set the year of redistributable to find; see below.
     var
      names: TArrayOfString;
      i: Integer;
      dName, key, year: String;
     begin
      // Year of redistributable to find; leave null to find installation for any year.
      year := '';
      Result := False;
      key := 'Software\Microsoft\Windows\CurrentVersion\Uninstall';
      // Get an array of all of the uninstall subkey names.
      if RegGetSubkeyNames(HKEY_LOCAL_MACHINE, key, names) then
       // Uninstall subkey names were found.
       begin
        i := 0
        while ((i < GetArrayLength(names)) and (Result = False)) do
         // The loop will end as soon as one instance of a Visual C++ redistributable is found.
         begin
          // For each uninstall subkey, look for a DisplayName value.
          // If not found, then the subkey name will be used instead.
          if not RegQueryStringValue(HKEY_LOCAL_MACHINE, key + '\' + names[i], 'DisplayName', dName) then
           dName := names[i];
          // See if the value contains both of the strings below.
          Result := (Pos(Trim('Visual C++ ' + year),dName) * Pos('Redistributable',dName) <> 0)
          i := i + 1;
         end;
       end;
     end;
    

    【讨论】:

    • 似乎最新的 msvc 2015 redist 被标记为“Microsoft Visual C++ 2015 x64 Minimum Runtime - 14.0.23026”,因此字符串中没有出现“Redistributable”一词。
    【解决方案4】:

    我知道这是一个非常古老的问题,但我遇到了这种情况,因为我无法进行 winregistry 检查,所以我采用了这种方法,

    基于此文件列表:https://matthew-brett.github.io/pydagogue/_sources/python_msvc.rst.txt

    我能够检查文件是否存在,例如 VCRedist 2015/2013 x86/x64:

    2015

    C:/Windows/System32/msvcp140.dll - x64

    C:/Windows/SysWOW64/msvcp140.dll" - x86

    2013

    C:/Windows/System32/msvcp120.dll - x64

    C:/Windows/SysWOW64/msvcp120.dll" - x86

    【讨论】:

      【解决方案5】:

      我正在处理 Visual C++ 2015-2019 可再发行包以及可能在 64 位操作系统上安装的 32 位。

      我修改user3433200 solution如下:

      function VCinstalled(const regKey: string): Boolean;
       { Function for Inno Setup Compiler }
       { Returns True if same or later Microsoft Visual C++ 2015 Redistributable is installed, otherwise False. }
       var
        major: Cardinal;
        minor: Cardinal;
        bld: Cardinal;
        rbld: Cardinal;
       begin
        Result := False;
      
        if RegQueryDWordValue(HKEY_LOCAL_MACHINE, regKey, 'Major', major) then begin
          if RegQueryDWordValue(HKEY_LOCAL_MACHINE, regKey, 'Minor', minor) then begin
            if RegQueryDWordValue(HKEY_LOCAL_MACHINE, regKey, 'Bld', bld) then begin
              if RegQueryDWordValue(HKEY_LOCAL_MACHINE, regKey, 'RBld', rbld) then begin
                  Log('VC 2015-2019 Redist Major is: ' + IntToStr(major) + ' Minor is: ' + IntToStr(minor) + ' Bld is: ' + IntToStr(bld) + ' Rbld is: ' + IntToStr(rbld));
                  { Version info was found. Return true if later or equal to our 14.23.27820.0 redistributable }
                  { Note brackets required because of weird operator precendence }
                  Result := (major >= 14) and (minor >= 23) and (bld >= 27820) and (rbld >= 0)
              end;
            end;
          end;
        end;
       end;
      
      function VCRedistNeedsInstall: Boolean;
      begin
       if NOT IsWin64 then 
        Result := not (VCinstalled('SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X86'))
       else if Is64BitInstallMode then
        Result := not (VCinstalled('SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64'))
       else
        Result := not (VCinstalled('SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86'));  
      end;
      

      在 Win 7 32bit 和 Win10 64bit 上测试。

      【讨论】:

        【解决方案6】:

        Comsci's answerMartin's answer 改编)很接近,但没有正确执行版本检查。 (例如,如果次要版本中有一个凸起并且内部版本号重置为零,它将失败。)这是该答案的更正版本,适用于 32 位和 64 位 Visual Studio 2015-2019 软件包。

        我发现当前的 64 位软件包如果已经安装会破坏运行时,所以在安装之前检查是必要的(直到微软修复了这个问题)。编辑:这可能已在 Visual Studio 16.10 (release notes) 中修复。

        与原始答案一样,这是基于Microsoft recommended way of determining whether the VC Redistributable is installed

        [Files]
        Source: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\v142\vcredist_x86.exe; DestDir: {tmp}; Flags: deleteafterinstall ignoreversion
        Source: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\v142\vcredist_x64.exe; DestDir: {tmp}; Flags: deleteafterinstall ignoreversion; Check: IsWin64
        
        [Run]
        Filename: {tmp}\vcredist_x86.exe; Parameters: /quiet /norestart; StatusMsg: "{#VCmsg32}"; Check: not VCRuntime32Installed
        Filename: {tmp}\vcredist_x64.exe; Parameters: /quiet /norestart; StatusMsg: "{#VCmsg64}"; Check: IsWin64 and not VCRuntime64Installed
        
        [Code]
        function VCRuntime32Installed: Boolean;
         var
          required_major: Cardinal;
          required_minor: Cardinal;
          required_bld: Cardinal;
          required_rbld: Cardinal;
          major: Cardinal;
          minor: Cardinal;
          bld: Cardinal;
          rbld: Cardinal;
          key: String;
         begin
          required_major := 14;
          required_minor := 29;
          required_bld := 30037;
          required_rbld := 0;
          Result := False;
          key := 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X86';
          if RegQueryDWordValue(HKLM32, key, 'Major', major) then begin
            if RegQueryDWordValue(HKLM32, key, 'Minor', minor) then begin
              if RegQueryDWordValue(HKLM32, key, 'Bld', bld) then begin
                if RegQueryDWordValue(HKLM32, key, 'Rbld', rbld) then begin
                    Log('vcruntime (x86) version: ' + IntToStr(major) + '.' + IntToStr(minor) + '.' + IntToStr(bld) + '.' + IntToStr(rbld));
                    Result := (major > required_major) or ((major = required_major) and ((minor > required_minor) or ((minor = required_minor) and ((bld > required_bld) or ((bld = required_bld) and (rbld >= required_rbld))))))
                end;
              end;
            end;
          end;
         end;
        function VCRuntime64Installed: Boolean;
         var
          required_major: Cardinal;
          required_minor: Cardinal;
          required_bld: Cardinal;
          required_rbld: Cardinal;
          major: Cardinal;
          minor: Cardinal;
          bld: Cardinal;
          rbld: Cardinal;
          key: String;
         begin
          required_major := 14;
          required_minor := 29;
          required_bld := 30037;
          required_rbld := 0;
          Result := False;
          key := 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X64';
          if RegQueryDWordValue(HKLM64, key, 'Major', major) then begin
            if RegQueryDWordValue(HKLM64, key, 'Minor', minor) then begin
              if RegQueryDWordValue(HKLM64, key, 'Bld', bld) then begin
                if RegQueryDWordValue(HKLM64, key, 'Rbld', rbld) then begin
                    Log('vcruntime (x64) version: ' + IntToStr(major) + '.' + IntToStr(minor) + '.' + IntToStr(bld) + '.' + IntToStr(rbld));
                    Result := (major > required_major) or ((major = required_major) and ((minor > required_minor) or ((minor = required_minor) and ((bld > required_bld) or ((bld = required_bld) and (rbld >= required_rbld))))))
                end;
              end;
            end;
          end;
         end;
        

        【讨论】:

          猜你喜欢
          • 2016-12-13
          • 2015-08-20
          • 2012-06-24
          • 2018-10-28
          • 1970-01-01
          • 2020-01-04
          • 2017-10-14
          • 2011-03-01
          • 2010-12-15
          相关资源
          最近更新 更多