Как получить правильное возвращаемое значение / статус VC++ 2005 в NSIS

Я хочу установить распространяемые пакеты Visual C++ для Visual Studio 2013 с помощью NSIS.

Однако правильный код выхода не возвращается. Я тестировал с несколькими типами вариаций. Лучшее, что я придумал, это:

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

Но когда я намеренно нажал на кнопку "Отмена" установки VC++2005, NSIS все равно воспринял ее как успешную установку (я получил диалоговое окно в инструкции MessageBox MB_OK|MB_ICONEXCLAMATION "No error")

Как я могу точно и правильно получить возвращенную ошибку (например, когда я сам "Отменил", установил установку)?

РЕДАКТИРОВАТЬ:

После помощи @Anders у меня теперь есть следующее, которое по-прежнему не удается (т.е. not installed даже когда установка VC++2005 была завершена. Я также пробовал разные параметры командной строки для установки 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

1 ответ

Возможно, vcredist_x86.exe неправильно возвращает код выхода из MsiExec?

Если ExecWait может найти и запустить процесс (IfErrors равно "false"), тогда NSIS гарантированно вернет правильный код завершения из дочернего процесса.

$0 != 0 на самом деле сравнение строк, и вы должны использовать $0 <> 0 сравнить 32-битные числа, но это не проблема в этом случае.

!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 
Другие вопросы по тегам