Exit from nested batch file

左心房为你撑大大i 提交于 2021-02-07 06:26:07

问题


I have 4 batch files, suppose a.bat, b.bat, c.bat and d.bat. Now these batch files are called in such a manner that a.bat calls b.bat, b.bat calls c.call and so on.

If I get any error in any batch file, I want to exit from the entire program by saying an error occurred, and mention which batch file had a problem. My question is, how can I do this?

Here I used exit /b but it only gets out from the current batch file and moves back into batch file from whence it was called:

a.bat

@echo. off
echo. this is batch 'a'
call b.bat

b.bat

@echo. off
echo. this is batch 'b'
call c.bat

c.bat

@echo. off
echo. this is batch 'c'

I get an error in batch 'C' - It should then report an error and exit, but it's moving back into batch 'B' somehow. Any idea on how to exit from a nested batch file?


回答1:


You can use a syntax error, this stop immediately the batch without closing the command window.

The :HALT functions calls the :__halt function only to supress the error message.

c.bat

@echo off
echo this is batch 'c'
echo An error occurs
call :HALT
exit /b

:HALT
call :__halt 2> nul
exit /b

:__halt
()



回答2:


You might try this (c.bat):

@echo. this is batch 'c'
@pause
exit



回答3:


You can use errorlevels with exit codes, as described here: http://www.robvanderwoude.com/errorlevel.php

In particular, if you want to do a manual error, then c.bat or b.bat should explicitly have an exit code specified with

EXIT /b 1

(or a number of your choosing), but if you just want windows automatic errors to count, then right after running b.bat or c.bat, you can just write

IF ERRORLEVEL 1 EXIT /b %ERRORLEVEL%

Which will propagate the same error up to the next program, so they can exit immediately if you so wish. Has the advantage that you can stop propagating upwards whenever you want.

(edit: to be clear, the second line of code mentioned here is necessary in all but the bottom-level program whether you're using manual or automatic errors)




回答4:


jeb's fatal syntax error method works, but it does not properly terminate any active SETLOCAL.

For example, here is fatalTest.bat:

@echo off
setlocal enableDelayedExpansion
set test=AFTER main SETLOCAL
call :sub
echo returning from main  NEVER REACHED
exit /b

:sub
setlocal
set test=AFTER sub SETLOCAL
set test
call :ExitBatch
echo returning from sub2 NEVER REACHED
exit /b


:ExitBatch
call :__exitBatch 2>nul
:__ExitBatch
for

And here is sample run output demonstrating how test is still defined and delayed expansion is still enabled after batch processing terminates:

C:\test>fatalTest
test=AFTER sub SETLOCAL

C:\test>echo !test!
AFTER sub SETLOCAL

C:\test>

It is now impossible to restore the environment to a pre-batch state. The CMD.EXE session should be terminated.


Here is an improved CtrlCTest.bat version that properly terminates any active SETLOCAL upon batch termination. It uses a surprising technique to programmatically "press" Ctrl-C that I learned about at Why does a non-interactive batch script think I've pressed control-C?

@echo off
setlocal enableDelayedExpansion
set test=AFTER main SETLOCAL
call :sub
echo returning from main  NEVER REACHED
exit /b

:sub
setlocal
set test=AFTER sub SETLOCAL
set test
call :ExitBatch
echo returning from sub2 NEVER REACHED
exit /b


:ExitBatch - Cleanly exit batch processing, regardless how many CALLs
if not exist "%temp%\ExitBatchYes.txt" call :buildYes
call :CtrlC <"%temp%\ExitBatchYes.txt" 1>nul 2>&1
:CtrlC
cmd /c exit -1073741510

:buildYes - Establish a Yes file for the language used by the OS
pushd "%temp%"
set "yes="
copy nul ExitBatchYes.txt >nul
for /f "delims=(/ tokens=2" %%Y in (
  '"copy /-y nul ExitBatchYes.txt <nul"'
) do if not defined yes set "yes=%%Y"
echo %yes%>ExitBatchYes.txt
popd
exit /b

And here is sample run output. You can see that delayed expansion is no longer active, and test is no longer defined:

C:\test>CtrlCTest
test=AFTER sub SETLOCAL

C:\test>echo !test!
!test!

C:\test>set test
Environment variable test not defined

C:\test>

You could put the :ExitBatch routine in a stand-alone ExitBatch.bat script that resides somewhere within your PATH, and then any batch can conveniently CALL the utility as needed.

@echo off
:ExitBatch - Cleanly exit batch processing, regardless how many CALLs
if not exist "%temp%\ExitBatchYes.txt" call :buildYes
call :CtrlC <"%temp%\ExitBatchYes.txt" 1>nul 2>&1
:CtrlC
cmd /c exit -1073741510

:buildYes - Establish a Yes file for the language used by the OS
pushd "%temp%"
set "yes="
copy nul ExitBatchYes.txt >nul
for /f "delims=(/ tokens=2" %%Y in (
  '"copy /-y nul ExitBatchYes.txt <nul"'
) do if not defined yes set "yes=%%Y"
echo %yes%>ExitBatchYes.txt
popd
exit /b



回答5:


If the .BAT file is under TakeCommand, use CANCEL.



来源:https://stackoverflow.com/questions/17655345/exit-from-nested-batch-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!