Reputation: 73
Before installing the software, I need to check if the Visual C++ 2017 redistributable(x86)
is installed or not. If it is not installed, while installing the software first I can install the redistributable executable.
When i installed it manually it is showing in the below path:
Computer\HKEY_CLASSES_ROOT\Installer\Dependencies\VC,redist.x86,x86,14.16,bundle\Dependents\{67f67547-9693-4937-aa13-56e296bd40f6}
Please help me how to check the above path using NSIS
?
So that If the executable is not present before installing the software i can install it with the below code:
!insertmacro MUI_LANGUAGE "English"
Section "MyApp"
SetOutPath $INSTDIR
File "\Desktop\Common\vcredist_x86.exe"
ExecShell "" "$INSTDIR\vcredist_x86.exe"
SectionEnd
Upvotes: 5
Views: 4678
Reputation: 101756
!include LogicLib.nsh
!macro _RegKeyExistsIn _key _pack _t _f
#DBG: 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
but I don't know if this is the best way to detect the redistributable because you are checking a specific minor version and some unknown GUID.
The documentation says that you should check 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 "" ${_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
Upvotes: 2
Reputation: 180050
Simpler version, using the "Version" string key and a string comparison.
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
Downside: this could theoretically give a false negative if "v14.100.x.y" is installed. But the impact would only be that you try to install the 14.16 redistributable, which does nothing.
[Edit] Bonus code: If you build vswhere, you can use it to extract the redistributable from your Visual C++ install directory:
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
Note that the section is optional, it's conditionally enabled using the test detailed before:
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
Upvotes: 2
Reputation: 5472
The also correct (and by many developers recommended) way is to simply install the Runtime silently.
It will not harm any components or software and it is much quicker and easier.
Upvotes: 0