MajorInc
MajorInc

Reputation: 354

batch start persist specific variable

I have a.bat which has a variable %errorlevel%, and the following line which calls b.bat:

start /wait cmd /c b.bat

If b.bat sets the %errorlevel% (e.g. errorlevel = 5)

How is it possible for me to persist only this %errorlevel% variable in a.bat, without using the CALL command.

The reason I don't want to use CALL is because b.bat contains some variables that I do not want to persist.

Upvotes: 0

Views: 511

Answers (2)

dbenham
dbenham

Reputation: 130849

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

Upvotes: 1

Gerardo Lima
Gerardo Lima

Reputation: 6703

You don't have to expose inner variables to communicate between scripts. You can use regular arguments to send values to the called script and get its numeric result from %ERRORLEVEL% environment variable. In the following sample, a.cmd passes an argument to b.cmd and receive the result of its execution (from %ERRORLEVEL%):

:: a.cmd ----
SETLOCAL
SET ARGUMENT=123
CALL b.cmd "%ARGUMENT%"
SET RESULT=%ERRORLEVEL%
ECHO B returned this numeric value as result (%RESULT%)

:: b.cmd ----
SETLOCAL
SET OTHERVAR=%~1
ECHO B received this value as argument (%OTHERVAR%)
EXIT /B 33000

I reinforce the suggestion to avoid using reserved names for variables (as @dbenham also commented).

Upvotes: 1

Related Questions