NSIS 中止和错误级别
Posted
技术标签:
【中文标题】NSIS 中止和错误级别【英文标题】:NSIS Abort and errorlevel 【发布时间】:2017-06-27 15:47:44 【问题描述】:我正在使用 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 代码中我明确设置了错误级别并使用 Abort 退出。
在我的 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 中检索我的安装程序的退出代码?
【问题讨论】:
你是如何开始这个过程的? 【参考方案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%
【讨论】:
谢谢。我稍微编辑了这个问题,只是为了更清楚地了解我如何启动安装程序(确实很简单)。在你的帮助下,我现在可能知道出了什么问题。我“直接”调用安装程序 exe,没有start /wait。但由于 NSIS 将安装程序构建为“非控制台应用程序”,我应该选择
start /wait(也是因为否则脚本将不会停止)。我会试试的。【参考方案2】:
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)
当您在 cmd shell 中运行该命令时,一开始您无法意识到 shell 没有等待。然后,如果您检查 ERRORLEVEL,您可能会感到惊讶(就像我一样)
如果您想在交互模式下运行 foo.exe 时测试 ERRORLEVEL,可能会发生同样的事情。您无法意识到 foo 与外壳“分离”。在这种情况下检查 shell %ERRORLEVEL% 是没有用的。
最后你发现有人建议非控制台应用程序必须使用 start /wait
http://forums.winamp.com/showpost.php?p=2530597&postcount=2
所以你应该改用这个命令行:
start /wait foo.exe /S /D=C:\Program Files\Foo`
【讨论】:
以上是关于NSIS 中止和错误级别的主要内容,如果未能解决你的问题,请参考以下文章