Tanel
I came across an issue that could be put in the "requested feature is lacking"-category. I also thought of a workaround for it. But to be honest, the workaround is not elegant and makes the code even bulkier. To get an understanding of the problem you should look at the output data. The issue, in short, is that there should be a way to - on request - exit the called batch file and return control to where it was called from. Using "goto :EOF" will not always work and "exit" will kill your cmd.exe-process. I know this is the place to ask when it comes to more in-depth questions. So if there is anyone out there who has experience with this specific issue I would be very thankful for your input.
Output of broken code:
Output with workaround applied:This the BEGINING of batch file 1.
This is a FUNCTION in batch file 1.
This the BEGINING of batch file 2.
This is a FUNCTION in batch file 2.
ERROR occured, do you want to CONTINUE? [Y/N] n
This is the END of batch file 2.
This is the MAIN of batch file 2.
Above should only be printed if you chose to continue.
This is the END of batch file 2.
This the END of batch file 1.
Press any key to continue . . .
Lab2-TestFile1.bat:This the BEGINING of batch file 1.
This is a FUNCTION in batch file 1.
This the BEGINING of batch file 2.
This is a FUNCTION in batch file 2.
ERROR occured, do you want to CONTINUE? [Y/N] n
This is the END of batch file 2.
This the END of batch file 1.
Press any key to continue . . .
Code: Select all
@echo off
setlocal EnableDelayedExpansion
set extfile=Lab2-TestFile2.bat
REM ---- MAIN
echo This the BEGINING of batch file 1.
echo.
call :TestFunctionOne
echo.
call %extfile%
echo.
call :End
REM ---- FUNCTIONS
:TestFunctionOne
echo This is a FUNCTION in batch file 1.
goto :EOF
:End
echo This the END of batch file 1.
pause
exit
Code: Select all
@echo off
setlocal EnableDelayedExpansion
REM ---- MAIN
echo This the BEGINING of batch file 2.
echo.
call :TestFunctionTwo
REM ---- UGLY WORKAROUND, UNCOMMENT TO TAKE INTO USE
::if "%errorlevel%" NEQ "0" goto :EOF
echo.
echo This is the MAIN of batch file 2.
echo Above should only be printed if you chose to continue.
goto :End
REM ---- FUNCTIONS
:TestFunctionTwo
echo This is a FUNCTION in batch file 2.
call :GetUserInput
goto :EOF
:GetUserInput
echo.
set /p "choice=ERROR occured, do you want to CONTINUE? [Y/N] "
if /i "%choice%" equ "Y" goto :EOF
if /i "%choice%" equ "N" goto :End
echo "%choice%" is not a valid choice, please try again^^!
goto :GetUserInput
REM ---- This funtion should ALWAYS return to batch file 1
:End
echo.
echo This is the END of batch file 2.
REM ---- GOES WITH THE UGLY WORKAROUND ABOVE, UNCOMMENT TO TAKE INTO USE
::exit /B 1
REM ---- Not always returning to batch file 1
goto :EOF
----------------------------
#2 18 Jan 2011 18:15
jeb
Hi Tan,
nice to meet you here.
I understand your problem as:
Exit a batch-file immediatly, even in nested functions.
I suppose the key could be the "start /b /wait cmd /c bat2.bat"
I tested it with these to batch files
bat1.bat
Code: Select all
@ECHO OFF
echo This is %~0
call :func
echo end of %~0
goto :eof
:func
echo func %~0 ... Now calling bat2
start /b /wait cmd /c bat2.bat
echo func %~0
goto :eof
bat2.bat
@ECHO OFF
echo This is %~0
call :func
echo end of %~0
goto :eof
:func
echo func %~0 .... Now exit
exit
echo func %~0
goto :eof
hope it helps
jeb
----------------------------
#3 19 Jan 2011 15:29
Tanel
Thank you jeb! That worked as a charm! Very much appreciated.
All the best,
Tanel
----------------------------
#4 19 Jan 2011 17:59
avery_larry
How about simply:
exit /b
instead of exit?
----------------------------
#5 19 Jan 2011 18:26
jeb
It doesn't work, that's the cause.
In the most cases the behaviour of exit /b is good, but not here.
exit /b only exits the last "call/function"-level, but not the entire batch as Tanel wanted.
----------------------------
#6 19 Jan 2011 19:23
avery_larry
But exit /b does exactly as described -- oh just never mind.
----------------------------
#7 20 Jan 2011 11:29
Tanel
avery_larry, I tried "exit /b" before posting this thread and just as jeb pointed out, it does not work.
----------------------------
#8 21 Jan 2011 16:34
avery_larry
I wanted the same thing a long time ago. It forced me to understand how subroutines and call functions work, and then I was able to change my scripts to utilize exit /b and subsequent errorlevels.
I felt that using start "" cmd was a bit of a "sledgehammer" approach. Functional certainly, and I used it for a good while. But then I started using subroutines instead of separate batch files, I started using errorlevels, and I started using the && & and || functions to allow for a "chained" exit when appropriate.
But it's clearly in a category of personal preference. Each person will have a different idea of "elegant". So it's more of a philosophical discussion.
----------------------------
#9 24 Jan 2011 14:27
Tanel
But it's clearly in a category of personal preference. Each person will have a different idea of "elegant". So it's more of a philosophical discussion.avery_larry wrote:
I wanted the same thing a long time ago. It forced me to understand how subroutines and call functions work, and then I was able to change my scripts to utilize exit /b and subsequent errorlevels.
I felt that using start "" cmd was a bit of a "sledgehammer" approach. Functional certainly, and I used it for a good while. But then I started using subroutines instead of separate batch files, I started using errorlevels, and I started using the && & and || functions to allow for a "chained" exit when appropriate.
Do I understand you correctly in that you'd rather use...
Code: Select all
call :TestFunctionTwo || goto :eof
Code: Select all
exit /b 1
----------------------------
#10 24 Jan 2011 18:31
avery_larry
With multiple batch files, you can still do the same thing:
Code: Select all
call otherbat.cmd || goto :eof
Also, if you do any variable sharing, starting a new cmd will typically inherit the current variables, but any variable manipulation will be lost on the "exit" command. That's actually the primary factor on why I stopped using the "call cmd ..." and exit method. I needed to manipulate variables in the other batch files.
When I finally decided to figure out how to get rid of my "start cmd ..." coding, I ended up consolidating some of my script files -- using call labels for some. For other script files that would be used from multiple script files (where a call :label would have to be added to multiple scripts), I decided that I really wanted to have a more robust, generalized scripting concept. And that's the other big problem I have with the "start cmd ..." method is that you ALWAYS have to call that batch file using a "start cmd ..." command, otherwise the "exit" will kill everything instead of actually returning to the point where it was called. So the "generic" script concept would give you the concept of a normal exit (goto :eof) or an error exit (exit /b 1).
Of course, as I already said, that's all more about personal preferences. Many would say using common variables in script files is a very bad idea. Or having a called script file manipulate variables, yet that's precisely what I often do.
----------------------------
#11 24 Jan 2011 19:34
jeb
You could dynamically import/include your other batch files,
instead of calling them as external software, so you can use a "single" file solution again.
It's a little bit slower at startup, but in my opinion it's the best way for me.
----------------------------
#12 24 Jan 2011 20:06
Tanel
I do understand the general idea; I've been applying the same concept in .sh/.ksh/.csh/.bash-scripts for quite some time. However I cannot see it solving the issue at top and it seems jeb is of the same opinion. Could you be so kind and provide an example using the top code as a base?avery_larry wrote:
With multiple batch files, you can still do the same thing:
call otherbat.cmd || goto :eof
And then otherbat.cmd can have a "normal" exit using goto :eof, or a "break out" exit with exit /b or a "kill everything error" exit with exit /b 1. You can even get fancy with different errorlevels.
I can see the reasoning behind wanting to use variable sharing, that's more than a valid reason to use call instead of start.Also, if you do any variable sharing, starting a new cmd will typically inherit the current variables, but any variable manipulation will be lost on the "exit" command. That's actually the primary factor on why I stopped using the "call cmd ..." and exit method. I needed to manipulate variables in the other batch files.
Yes, this is the problem I was having and the issues of using goto :eof is high-lighted in my first message. Unless you provide a code sample of how to solve the original problem (described at the very top) I unfortunately cannot come to any other conclusion than that you've misunderstood the issue.And that's the other big problem I have with the "start cmd ..." method is that you ALWAYS have to call that batch file using a "start cmd ..." command, otherwise the "exit" will kill everything instead of actually returning to the point where it was called. So the "generic" script concept would give you the concept of a normal exit (goto :eof) or an error exit (exit /b 1).