NSIS中止和错误级别

时间:2017-06-27 15:47:44

标签: windows error-handling installer nsis abort

我正在使用NSIS构建一个简单的安装程序,并希望在批处理脚本中以静默模式运行它,最后我会检查ERRORLEVEL:

REM a simple test
REM get into folder and run the installer
cd /d my_installer_path 
my_installer_made_with_nsis.exe /S
if %ERRORLEVEL% NEQ 0 echo something has gone wrong

现在,似乎my_installer_made_with_nsis.exe始终返回%ERRORLEVEL% 0,即使在nsi代码中我明确设置了错误级别并退出中止。

在我的nsi脚本中,我使用像

这样的ErrorHandling函数
Function ErrorHandler
IfSilent +2 0
MessageBox MB_ICONSTOP "$err_msg"

DetailPrint "$err_msg"
SetErrorlevel 5 ; <---- APPARENTLY DOES NOT WORK
Abort
FunctionEnd

然后,在我的代码中,我像这样调用错误处理程序:

...
StrCpy $err_msg "An exception occurred: blah blah"
Call ErrorHandler

我希望cmd shell中的外部%ERRORLEVEL%为5,但它始终为0.

也许我在NSIS中错误地理解了ErrorLevel的整个概念,但在这种情况下有没有办法从命令shell中检索我的安装程序的退出代码?

2 个答案:

答案 0 :(得分:1)

SetErrorlevel正常工作,意思是,它设置了流程的退出代码。 %ERRORLEVEL%不一定是子进程的退出代码,尤其是在调用GUI进程时。你的问题是你的批处理文件/ cmd.exe,而不是NSIS。

Function MyAbortFunction
SetErrorlevel 5
Abort
FunctionEnd

Section
System::Call 'Kernel32::GetEnvironmentVariable(t "TestAbort", p 0, i0)i.r0'
${If} $0 = 0
    System::Call 'Kernel32::SetEnvironmentVariable(t "TestAbort", t "1")'
    ExecWait '"$ExePath"' $0 ; Run the test instance of our self
    MessageBox MB_OK "Exit code = $0" ; This will be 5
    SetErrorlevel $0 ; Make the parent use the same code in case you are testing in cmd.exe
${Else}
    Call MyAbortFunction
${EndIf}
SectionEnd

在cmd.exe中,这可以正常工作:

start "" /WAIT "c:\my\path\to\Test.exe"
echo %errorlevel%

答案 1 :(得分:0)

nsi脚本没什么问题

解决方案是: 在批处理脚本中使用 start /wait

运行安装程序

这很简单,但对于NSIS的初学者来说并不那么明显。

如果您必须等待安装程序继续执行批处理脚本,则必须使用start /wait,但首先您可能会错过,并且在谈到ERRORLEVEL时也会错过效果。

NSIS手册有许多运行静默卸载程序的好例子http://nsis.sourceforge.net/Docs/Chapter4.html#silent

但它没有提到start /wait

的需要

如果您参考手册示例:

 foo.exe /S /D=C:\Program Files\Foo

(并假设foo非常简单, FAST 用于测试sakes)

当您在cmd shell中运行该命令时,您最初无法意识到shell没有等待。然后,如果你检查ERRORLEVEL,你可能会感到惊讶(像我一样)

如果要在交互模式下运行foo.exe时要测试ERRORLEVEL,可能会发生同样的情况。你无法意识到foo与shell“分离”。在这种情况下检查shell%ERRORLEVEL%是没有用的。

然后最后你发现有人建议必须使用启动/等待非控制台应用

http://forums.winamp.com/showpost.php?p=2530597&postcount=2

所以你应该使用这个命令行:

start /wait foo.exe /S /D=C:\Program Files\Foo`