This answer has been edited significantly since it was originally posted.
Your command should work as currently written, although I don't see any advantage to using START. It would be much simpler and more efficient to simply use:
cmd /c "b.bat"
The ERRORLEVEL that was set by b.bat should be returned by the CMD command. Of course this will not work if you created your own environment variable named ERRORLEVEL that masks the dynamic value maintained by Windows.
However, I think it would be better, (if possible), to modify b.bat so that it has SETLOCAL
at the top. Any variables defined by b.bat are temporary and forgotten once the script ends. Then you can use CALL and the variables in b.bat will be gone, but the ERRORLEVEL will be set properly for the caller.
b.bat
@echo off
setlocal
set var=This value will be "forgotten" when b.bat ends
dir "This does not exist so ERRORLEVEL will be set to 1"
caller.bat
@echo off
set var=
call b.bat
echo ERRORLEVEL=%errorlevel%
set var
But based on your comment, it sounds as though you have a line in b.bat like the following:
set errorlelvel=%errorsaved%
You should never define your own value for ERRORLEVEL like that because it breaks the functionality of what ERRORLEVEL is supposed to be used for.
Instead you should use EXIT /B to set the errorlevel at the end of the script
@echo off
setlocal
...
set someVar=anything. This value will be gone at script end because of SETLOCAL
...
someCommandThatGeneratesAnError
set errorsaved=%errorlevel%
...
exit /b %errosaved%
If you are trying to selectively persist a user defined variable from b.bat (not ERRORLEVEL), then you really should modify b.bat to have SETLOCAL
at the top, and then use ENDLOCAL
coupled with any one of a number of methods to persist a value across the ENDLOCAL barrier. Have a look at the top 3 voted answers to Make an environment variable survive ENDLOCAL