如何使用 NSIS 检查是否安装了 Visual C++ 2017 可再发行 x86
How to check Visual C++ 2017 redistributable x86 is installed or not using NSIS
在安装软件之前,我需要检查是否安装了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
!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 [=11=] HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Installed"
ReadRegDWORD HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Major"
ReadRegDWORD HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Minor"
${If} [=11=] <> 0
DetailPrint "Found version ."
${If} " " VerCheck2=> "14 16"
DetailPrint "The installed version is usable"
${Else}
DetailPrint "Must install redist"
${EndIf}
${Else}
DetailPrint "Must install redist"
${EndIf}
SectionEnd
同样正确的(许多开发人员推荐的)方法是静默安装运行时。
它不会损害任何组件或软件,而且更快更容易。
更简单的版本,使用 "Version" 字符串键和字符串比较。
Section "CheckVCRedist"
ReadRegStr [=10=] HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Version"
DetailPrint "Found version [=10=]"
; Check for 14.16.27027 [sic]
${If} [=10=] >= "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 Studio17\Community\VC\Redist\MSVC.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 [=12=] HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x64" "Version"
DetailPrint "Found version [=12=]"
${If} [=12=] >= "v${RedistVer1}.${RedistVer2}.${RedistVer3}.${RedistVer4}"
DetailPrint "VC++ redistributable already present"
${Else}
DetailPrint "Installing VC++ redistributable."
SectionSetFlags ${VCRedist_id} 1 ; Selected
${EndIf}
FunctionEnd
在安装软件之前,我需要检查是否安装了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
!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 [=11=] HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Installed"
ReadRegDWORD HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Major"
ReadRegDWORD HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Minor"
${If} [=11=] <> 0
DetailPrint "Found version ."
${If} " " VerCheck2=> "14 16"
DetailPrint "The installed version is usable"
${Else}
DetailPrint "Must install redist"
${EndIf}
${Else}
DetailPrint "Must install redist"
${EndIf}
SectionEnd
同样正确的(许多开发人员推荐的)方法是静默安装运行时。
它不会损害任何组件或软件,而且更快更容易。
更简单的版本,使用 "Version" 字符串键和字符串比较。
Section "CheckVCRedist"
ReadRegStr [=10=] HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x86" "Version"
DetailPrint "Found version [=10=]"
; Check for 14.16.27027 [sic]
${If} [=10=] >= "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 Studio17\Community\VC\Redist\MSVC.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 [=12=] HKLM "SOFTWARE\Microsoft\VisualStudio.0\VC\Runtimes\x64" "Version"
DetailPrint "Found version [=12=]"
${If} [=12=] >= "v${RedistVer1}.${RedistVer2}.${RedistVer3}.${RedistVer4}"
DetailPrint "VC++ redistributable already present"
${Else}
DetailPrint "Installing VC++ redistributable."
SectionSetFlags ${VCRedist_id} 1 ; Selected
${EndIf}
FunctionEnd