I want to silently install Visual C++ Redistributable Packages for Visual Studio 2013 with NSIS.
However, the correct exit code is not being returned. I tested with several types of variations. The best I came up with is:
DetailPrint "Installing VC++ 2005"
File "${STOCKINPUTFOLDER}\bin\Debug\vcredist_x86.EXE"
ClearErrors
ExecWait "$OUTDIR\vcredist_x86.EXE /q:a /c:$\"msiexec /i vcredist.msi /qb /norestart$\"" $0 ; also can use /qn
;do not delete the file out-rightly so that evaluation of IfErrors below is clean
IfErrors execError noError
execError:
Goto ShortEndInstall
ShortEndInstall:
MessageBox MB_OK|MB_ICONEXCLAMATION "ShortEndInstall"
Delete "$OUTDIR\vcredist_x86.EXE" ;we did not delete the file outrightly so that evaluation of IfErrors is clean
Quit
noError:
${If} $0 != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "You did not complete the installation of the VC++ 2005 re-distributable. Installation will now abort. Return code $0"
Goto ShortEndInstall
${EndIf}
MessageBox MB_OK|MB_ICONEXCLAMATION "No error"
Delete "$OUTDIR\vcredist_x86.EXE" ;we did not delete the file outrightly so that evaluation of IfErrors is clean
But when I intentionally clicked on the "Cancel" button of the VC++2005 installation, NSIS still took it as being successful installation (I got the dialog box at instruction MessageBox MB_OK|MB_ICONEXCLAMATION "No error"
)
How can I accurately and correctly get the returned error (e.g. when I "Cancel"ed the installation myself)?
EDIT:
Following the help by @Anders I now have the following, which still fails (i.e. not installed
even while the VC++ 2005 installation was completed. I also tried different command line options for the installation VC++2005)
!include LogicLib.nsh
!include WordFunc.nsh
!define VERSION "8.1.0.0"
!define SHORTVERSION "8.1"
!define NAME "SchoolServer MainHost"
!define SHARPDEVFOLDER "..\..\..\.."
!define STOCKINPUTFOLDER "${SHARPDEVFOLDER}\SchoolServer_100\SS-Server"
!define PARENTSTOCKFOLDER "${SHARPDEVFOLDER}\SchoolServer_100"
!define MSVC2005_X86REDIST_PRODUCTCODE {A49F249F-0C91-497F-86DF-B2585E8E76B7}
!define MSVC2005_X86REDIST_PRODUCTCODE_SP1 {7299052B-02A4-4627-81F2-1818DA5D550D}
!define MSVC2005_X86REDIST_PRODUCTCODE_SP1_UP {837B34E3-7C30-493C-8F6A-2B0F04E2912C}
!define INSTALLSTATE_DEFAULT 5
!define MACRO_check_successful_install "!insertmacro check_vc_install"
!define MACRO_check_successful_install_exclusive_2005 "!insertmacro check_vc_install_exclusive_2005"
Var function_call_return
Var tested_vc_key
!macro check_vc_install install_key
DetailPrint "Copying ${install_key} to tested_vc_key"
StrCpy $tested_vc_key ${install_key}
call check_vc_install_normal
!macroend
!macro check_vc_install_exclusive_2005 install_key
StrCpy $tested_vc_key ${install_key}
call check_vc_install_exclusive_2005
!macroend
OutFile "${NAME} Lite Installer - ${SHORTVERSION}.exe"
#Sections
Section "Installation"
SetShellVarContext all
SetOutPath "$INSTDIR"
SetRebootFlag false
DetailPrint "Installing VC++ 2005"
File "${STOCKINPUTFOLDER}\bin\Debug\vcredist_x86.EXE"
ClearErrors
ExecWait "$OUTDIR\vcredist_x86.EXE /q:a /c:$\"msiexec /i vcredist.msi /qb /norestart$\" " $0 ; also can use /qn
;we will not delete the file out-rightly so that evaluation of IfErrors below is clean
IfErrors execError noError
execError:
MessageBox MB_OK|MB_ICONEXCLAMATION "First line error!"
Goto ShortEndInstall
ShortEndInstall:
MessageBox MB_OK|MB_ICONEXCLAMATION "Installation of Microsoft Visual C++ 2005 runtime libraries failed!"
Delete "$OUTDIR\vcredist_x86.EXE" ;we did not delete the file outrightly so that evaluation of IfErrors is clean
;Quit
Return
noError:
;if no error, then check the exit code (https://sourceforge.net/p/nsis/mailman/message/22965694/ [use timemachine if 404 error. Page was accessed June 26, 2017])
${If} $0 != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "You did not complete the installation of the VC++ 2005 re-distributable. Installation will now abort. [Error $0]"
Goto ShortEndInstall
${EndIf}
ClearErrors
${MACRO_check_successful_install} ${MSVC2005_X86REDIST_PRODUCTCODE}
${If} $function_call_return == "installed"
Goto ContinueInstallation
${Else}
${MACRO_check_successful_install} ${MSVC2005_X86REDIST_PRODUCTCODE_SP1}
${If} $function_call_return == "installed"
Goto ContinueInstallation
${Else}
${MACRO_check_successful_install} ${MSVC2005_X86REDIST_PRODUCTCODE_SP1_UP}
${If} $function_call_return == "installed"
Goto ContinueInstallation
${Else}
${MACRO_check_successful_install_exclusive_2005} ${MSVC2005_X86REDIST_PRODUCTCODE}
${If} $function_call_return == "installed"
Goto ContinueInstallation
${Else}
${MACRO_check_successful_install_exclusive_2005} ${MSVC2005_X86REDIST_PRODUCTCODE_SP1}
${If} $function_call_return == "installed"
Goto ContinueInstallation
${Else}
${MACRO_check_successful_install_exclusive_2005} ${MSVC2005_X86REDIST_PRODUCTCODE_SP1_UP}
${If} $function_call_return == "installed"
Goto ContinueInstallation
${Else}
DetailPrint "Quiting... [Returned value: $function_call_return]"
Goto ShortEndInstall
${EndIf}
${EndIf}
${EndIf}
${EndIf}
${EndIf}
${EndIf}
ContinueInstallation:
Delete "$OUTDIR\vcredist_x86.EXE" ;we did not delete the file outrightly so that evaluation of IfErrors is clean
CreateDirectory "$INSTDIR\idcard"
File /r "${STOCKINPUTFOLDER}\bin\Debug\idcard"
SectionEnd
Function check_vc_install_normal
DetailPrint "check_vc_install_normal: Checking installation of $tested_vc_key"
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "ProductName", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
ClearErrors
${If} $0 == 0
DetailPrint "ProductName: $1"
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "AssignmentType", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "AssignmentType: $1"
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "PackageCode", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "PackageCode: $1"
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "VersionString", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "VersionString: $1"
StrCpy $function_call_return "installed"
${Else}
DetailPrint "Not installed [$0] [from check_vc_install_normal]"
StrCpy $function_call_return "not installed"
${EndIf}
FunctionEnd
Function check_vc_install_exclusive_2005
DetailPrint "check_vc_install_exclusive_2005: Checking special vc2005 installation of $tested_vc_key"
ClearErrors
System::Call 'MSI::MsiQueryProductState(t "$tested_vc_key")i.r0'
${If} ${INSTALLSTATE_DEFAULT} = $0
StrCpy $function_call_return "installed"
${Else}
DetailPrint "Not installed [$0] [from check_vc_install_exclusive_2005]"
StrCpy $function_call_return "not installed"
${EndIf}
FunctionEnd
Perhaps vcredist_x86.exe is not returning the exit code correctly from MsiExec?
If ExecWait
is able to find and start the process (IfErrors
is "false") then NSIS is guaranteed to return the correct exit code from the child process.
$0 != 0
is actually a string comparison and you should be using $0 <> 0
to compare 32-bit numbers but it is not the problem in this case.
!include LogicLib.nsh
Section
ExecWait '"cmd" /c exit 0' $0
${If} ${Errors}
${OrIf} $0 <> 0
Abort "Error, child process exited with $0" # Will not abort here
${EndIf}
ExecWait '"cmd" /c exit 1234' $0
${If} ${Errors}
${OrIf} $0 <> 0
Abort "Error, child process exited with $0" # Will abort here
${EndIf}
SectionEnd