0
votes

I'm building a simple installer with NSIS, and would like to run it in Silent mode inside a batch script, where in the end I would check the ERRORLEVEL like that:

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

Now, it seems that my_installer_made_with_nsis.exe always returns %ERRORLEVEL% 0 , even when inside the nsi code I explicitly set an error level and exit with Abort.

In my nsi script I use an ErrorHandling function like that

Function ErrorHandler
IfSilent +2 0
MessageBox MB_ICONSTOP "$err_msg"

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

Then, in my code I call the errorhandler like that:

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

I would expect outside in the cmd shell that %ERRORLEVEL% was 5, but it is always 0.

Maybe I got wrong the whole concept of ErrorLevel in NSIS, but in that case is there a way to retrieve from the command shell the exit code of my installer?

2
And how are you starting the process? - Anders

2 Answers

3
votes

SetErrorlevel works correctly, meaning, it sets the exit code of the process. %ERRORLEVEL% is not necessarily the exit code of the child process, especially when you are invoking a GUI process. Your problem is with your batch-file/cmd.exe, not 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

In cmd.exe this works correctly:

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

Nothing is wrong with the nsi script

The solution is: inside a batch script run the installer with start /wait

Simple as that, but not so obvious for a beginner in NSIS.

Using start /wait becomes a necessity if you have to wait for the installer to proceed in your batch script, but at first you may miss that, and also miss the effects when speaking of ERRORLEVELs.

The NSIS manual has many good examples of Running a Silent Uninstaller http://nsis.sourceforge.net/Docs/Chapter4.html#silent

but it does not mention the need of start /wait

If you take the manual example:

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

(and suppose foo to be quite trivial and FAST for testing sakes)

When you run that command in a cmd shell, you cannot realize at first that the shell is not waiting. Then if you check the ERRORLEVEL you can be surprised (like me)

The same thing may happen if you want to test ERRORLEVELs when running foo.exe in interactive mode. You could not realize that foo is "separate" from the shell. Checking the shell %ERRORLEVEL% in that case is no use.

Then finally you find someone that suggest one must use start /wait for non console apps

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

So you should instead use this command line:

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