如何在 NSIS 中获得 VC++ 2005 的正确 return value/status
How to get the correct return value/status of VC++ 2005 in NSIS
我想用 NSIS 静默安装 Visual C++ Redistributable Packages for Visual Studio 2013。
但是,没有返回正确的退出代码。我测试了几种类型的变体。我想到的最好的是:
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$\"" [=13=] ; 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} [=13=] != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "You did not complete the installation of the VC++ 2005 re-distributable. Installation will now abort. Return code [=13=]"
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安装的"Cancel"按钮时,NSIS仍然认为安装成功(我在指令MessageBox MB_OK|MB_ICONEXCLAMATION "No error"
)
如何准确正确地获取返回的错误信息(例如我自己"Cancel"安装时)?
编辑:
在@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$\" " [=14=] ; 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} [=14=] != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "You did not complete the installation of the VC++ 2005 re-distributable. Installation will now abort. [Error [=14=]]"
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} [=14=] == 0
DetailPrint "ProductName: "
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "AssignmentType", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "AssignmentType: "
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "PackageCode", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "PackageCode: "
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "VersionString", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "VersionString: "
StrCpy $function_call_return "installed"
${Else}
DetailPrint "Not installed [[=14=]] [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} = [=14=]
StrCpy $function_call_return "installed"
${Else}
DetailPrint "Not installed [[=14=]] [from check_vc_install_exclusive_2005]"
StrCpy $function_call_return "not installed"
${EndIf}
FunctionEnd
也许 vcredist_x86.exe 没有 return 从 MsiExec 正确输入退出代码?
如果 ExecWait
能够找到并启动进程(IfErrors
是 "false"),那么 NSIS 可以保证 return 从子进程中获得正确的退出代码.
[=13=] != 0
实际上是一个字符串比较,您应该使用 [=14=] <> 0
来比较 32 位数字,但在这种情况下这不是问题。
!include LogicLib.nsh
Section
ExecWait '"cmd" /c exit 0' [=10=]
${If} ${Errors}
${OrIf} [=10=] <> 0
Abort "Error, child process exited with [=10=]" # Will not abort here
${EndIf}
ExecWait '"cmd" /c exit 1234' [=10=]
${If} ${Errors}
${OrIf} [=10=] <> 0
Abort "Error, child process exited with [=10=]" # Will abort here
${EndIf}
SectionEnd
我想用 NSIS 静默安装 Visual C++ Redistributable Packages for Visual Studio 2013。
但是,没有返回正确的退出代码。我测试了几种类型的变体。我想到的最好的是:
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$\"" [=13=] ; 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} [=13=] != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "You did not complete the installation of the VC++ 2005 re-distributable. Installation will now abort. Return code [=13=]"
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安装的"Cancel"按钮时,NSIS仍然认为安装成功(我在指令MessageBox MB_OK|MB_ICONEXCLAMATION "No error"
)
如何准确正确地获取返回的错误信息(例如我自己"Cancel"安装时)?
编辑:
在@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$\" " [=14=] ; 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} [=14=] != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "You did not complete the installation of the VC++ 2005 re-distributable. Installation will now abort. [Error [=14=]]"
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} [=14=] == 0
DetailPrint "ProductName: "
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "AssignmentType", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "AssignmentType: "
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "PackageCode", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "PackageCode: "
System::Call 'MSI::MsiGetProductInfo(t "$tested_vc_key", t "VersionString", t"?"r1, *i${NSIS_MAX_STRLEN})i.r0'
DetailPrint "VersionString: "
StrCpy $function_call_return "installed"
${Else}
DetailPrint "Not installed [[=14=]] [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} = [=14=]
StrCpy $function_call_return "installed"
${Else}
DetailPrint "Not installed [[=14=]] [from check_vc_install_exclusive_2005]"
StrCpy $function_call_return "not installed"
${EndIf}
FunctionEnd
也许 vcredist_x86.exe 没有 return 从 MsiExec 正确输入退出代码?
如果 ExecWait
能够找到并启动进程(IfErrors
是 "false"),那么 NSIS 可以保证 return 从子进程中获得正确的退出代码.
[=13=] != 0
实际上是一个字符串比较,您应该使用 [=14=] <> 0
来比较 32 位数字,但在这种情况下这不是问题。
!include LogicLib.nsh
Section
ExecWait '"cmd" /c exit 0' [=10=]
${If} ${Errors}
${OrIf} [=10=] <> 0
Abort "Error, child process exited with [=10=]" # Will not abort here
${EndIf}
ExecWait '"cmd" /c exit 1234' [=10=]
${If} ${Errors}
${OrIf} [=10=] <> 0
Abort "Error, child process exited with [=10=]" # Will abort here
${EndIf}
SectionEnd