【问题标题】:How to check Visual C++ 2017 redistributable x86 is installed or not using NSIS如何使用 NSIS 检查 Visual C++ 2017 可再发行 x86 是否已安装
【发布时间】:2019-01-27 16:17:26
【问题描述】:

在安装软件之前,我需要检查Visual C++ 2017 redistributable(x86) 是否安装。如果没有安装,在先安装软件时,我可以安装可再发行的可执行文件。

当我手动安装它时,它显示在以下路径中:

Computer\HKEY_CLASSES_ROOT\Installer\Dependencies\VC,redist.x86,x86,14.16,bundle\Dependents\{67f67547-9693-4937-aa13-56e296bd40f6}

请帮助我如何使用NSIS检查上述路径?

如果在安装软件之前可执行文件不存在,我可以使用以下代码安装它:

!insertmacro MUI_LANGUAGE "English"

Section "MyApp"

SetOutPath $INSTDIR
File "\Desktop\Common\vcredist_x86.exe"

ExecShell "" "$INSTDIR\vcredist_x86.exe"
SectionEnd

【问题讨论】:

    标签: nsis


    【解决方案1】:

    更简单的版本,使用“版本”字符串键和字符串比较。

    Section "CheckVCRedist"
    ReadRegStr $0 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86" "Version"
    DetailPrint "Found version $0"
    ; Check for 14.16.27027 [sic]
    ${If} $0 >= "v14.16.27024.01"
       DetailPrint "The installed version is usable"
    ${Else}
       DetailPrint "Must install redist"
    ${EndIf}
    SectionEnd
    

    缺点:如果安装了“v14.100.x.y”,理论上这可能会给出假阴性。但影响只会是您尝试安装 14.16 可再发行组件,它什么都不做。

    [编辑] 奖励代码:如果您构建 vswhere,您可以使用它从您的 Visual C++ 安装目录中提取可再发行组件:

    Section /o VCRedist VCRedist_id
        ; Use the "pluginsdir"; it's really the NSIS temp dir, and it's cleaned up at the end.
        InitPluginsDir
        SetOutPath "$pluginsdir" 
    
        ; Finding the correct redistributable is a bit of a problem. MSVC itself ships with an
        ; appropriate redistributable. It's location will likely be similar to
        ; C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.16.27012
        ; but the exact location of the Redist folder can differ. That's why vswhere.exe is used.
        ; Note that the vswhere used is the local one, NOT the one from
        ; Visual Studio itself (finding that would be a chicken-and-egg problem). This version
        ; is new enough to support the -find parameter, which is what we need to find the
        ; redistributable. Stuff the result in a temporary redist.path file.
        !system 'vswhere.exe -latest -find "VC/Redist/**/vc_redist.x64.exe" > redist.path' 
        !define /file REDISTPATH redist.path
        ; Check what version we found. This is used to decide at install time whether we need to
        ; unpack this redistributable.
        !getdllversion "${REDISTPATH}" RedistVer
        !echo "Including VC++ Redistributable Version ${RedistVer1}.${RedistVer2}.${RedistVer3}.${RedistVer4}"
    
        SetCompress off
        File "${REDISTPATH}"
        SetCompress auto
    
        ; Cleanup the temporary redist.path file which held the output of vswhere -find
        !system 'del redist.path'
    
        ExecWait "vc_redist.x64.exe"
    SectionEnd
    

    请注意,该部分是可选的,使用之前详述的测试有条件地启用它:

    Function VCRedistNeeded
        SetRegView 64 
        ReadRegStr $0 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" "Version"
        DetailPrint "Found version $0"
        ${If} $0 >= "v${RedistVer1}.${RedistVer2}.${RedistVer3}.${RedistVer4}"
           DetailPrint "VC++ redistributable already present"
        ${Else}
          DetailPrint "Installing VC++ redistributable."
          SectionSetFlags ${VCRedist_id} 1 ; Selected
        ${EndIf}
    FunctionEnd  
    

    【讨论】:

    • 它说它使用vswhere来查找redis,但实际上并没有使用它或在哪里/如何使用它?阅读注册表显然不可靠(在此处搜索更多信息,但...)
    • @IceFire:把它塞进.onInit。例如。 Function .onInit Call VCRedistNeeded FunctionEnd
    • 抱歉,我是瞎子,因为;和 !看起来如此相似,我没有找到 vswhere 调用......我的错。感谢您让我仔细检查!
    【解决方案2】:
    !include LogicLib.nsh
    
    !macro _RegKeyExistsIn _key _pack _t _f
    DetailPrint '${_key} ${_pack}'
    !insertmacro _LOGICLIB_TEMP
    !ifndef _RegKeyExistsIn_var
        !define _RegKeyExistsIn_var
        Var /Global _RegKeyExistsIn
    !endif
    StrCpy $_RegKeyExistsIn 0
    SetErrors
    EnumRegKey $_LOGICLIB_TEMP ${_pack} $_RegKeyExistsIn
        IntOp $_RegKeyExistsIn $_RegKeyExistsIn + 1
        StrCmp $_LOGICLIB_TEMP "" +3
        StrCmp $_LOGICLIB_TEMP "${_key}" "" -3
        ClearErrors
    IfErrors `${_f}` `${_t}`
    !macroend
    
    Section
    ${If} "Dependents{67f67547-9693-4937-aa13-56e296bd40f6}" RegKeyExistsIn 'HKCR "Installer\Dependencies\VC,redist.x86,x86,14.16,bundle"'
        DetailPrint "Found the key"
    ${Else}
        DetailPrint "Key does not exist"
    ${EndIf}
    SectionEnd
    

    但我不知道这是否是检测可再发行组件的最佳方法,因为您正在检查特定的次要版本和一些未知的 GUID。

    documentation 说你应该检查HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%vs-version%\VC\Runtimes\{x86|x64|ARM}
    old documentation

    !include LogicLib.nsh
    
    !ifmacrondef _VerCheck2=>
    !macro _VerCheck2_geq_imp l1 l2 r1 r2 _t _f
    !insertmacro _LOGICLIB_TEMP
    !define _VerCheck2_geq_imp _VerCheck2_geq_${__COUNTER__}
    StrCpy $_LOGICLIB_TEMP 0
    IntCmpU ${l1} ${r1} ${_VerCheck2_geq_imp}eq "" ${_VerCheck2_geq_imp}end
    StrCpy $_LOGICLIB_TEMP 1
    Goto ${_VerCheck2_geq_imp}end
    ${_VerCheck2_geq_imp}eq:
    IntCmpU ${l2} ${r2} "" "" ${_VerCheck2_geq_imp}end
    StrCpy $_LOGICLIB_TEMP 1
    ${_VerCheck2_geq_imp}end:
    !undef _VerCheck2_geq_imp
    !insertmacro _= $_LOGICLIB_TEMP 0 `${_f}` `${_t}`
    !macroend
    !macro _VerCheck2=> _lhs _rhs _t _f
    !insertmacro _VerCheck2_geq_imp ${_lhs} ${_rhs} `${_f}` `${_t}`
    !macroend
    !endif
    
    Section
    ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86" "Installed"
    ReadRegDWORD $1 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86" "Major"
    ReadRegDWORD $2 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86" "Minor"
    ${If} $0 <> 0
        DetailPrint "Found version $1.$2"
        ${If} "$1 $2" VerCheck2=> "14 16"
            DetailPrint "The installed version is usable"
        ${Else}
            DetailPrint "Must install redist"
        ${EndIf}
    ${Else}
        DetailPrint "Must install redist"
    ${EndIf}
    SectionEnd
    

    【讨论】:

    • 对于 32 位,您需要检查 HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\%vs-version%\VC\Runtimes\x86,因为它不会出现在64 位注册表路径。 (奇怪的是,这两个位置都存在 x64 注册表设置。)
    • @RobH:如果安装程序是 32 位,我发布的实际代码将从 32 位注册表中读取。
    【解决方案3】:

    同样正确(许多开发人员推荐)的方法是静默安装运行时。

    它不会损害任何组件或软件,并且更快更容易。

    【讨论】:

    • 缺点是您需要提取可再发行文件。
    • 我在静默安装时遇到了问题。它降级了用户安装的版本,Microsoft Word 停止工作......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    相关资源
    最近更新 更多