从嵌套批处理文件退出

时间:2013-07-15 13:25:23

标签: windows batch-file cmd call exit

我有4个批处理文件,假设a.bat,b.bat,c.bat和d.bat。现在调用这些批处理文件的方式是a.bat调用b.bat,b.bat调用c.call等等。

如果我在任何批处理文件中出现任何错误,我想通过说出错误退出整个程序,并提出哪个批处理文件有问题。 我的问题是,我该怎么做?

在这里,我使用了exit /b,但它只从当前批处理文件中退出,并从调用它的位置移回批处理文件中:

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'

我在批处理'C'中出错 - 然后应该报告错误并退出,但它会以某种方式回到批处理'B'。如何退出嵌套批处理文件?

5 个答案:

答案 0 :(得分:5)

您可以使用语法错误,这会立即停止批处理而不关闭命令窗口。

:HALT函数仅调用:__halt函数来抑制错误消息。

<强> 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
()

答案 1 :(得分:2)

您可以尝试此操作(c.bat):

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

答案 2 :(得分:2)

jeb的致命语法错误方法有效,但它没有正确终止任何活动的SETLOCAL。

例如,这是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

此处是示例运行输出,演示了如何定义测试,并且在批处理终止后仍然启用延迟扩展:

C:\test>fatalTest
test=AFTER sub SETLOCAL

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

C:\test>

现在无法将环境恢复到预批处理状态。应该终止CMD.EXE会话。


这是一个改进的CtrlCTest.bat版本,可以在批量终止时正确终止任何活动的SETLOCAL。它使用一种令人惊讶的技术以编程方式“按下”我在Why does a non-interactive batch script think I've pressed control-C?

学到的Ctrl-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

这是样本运行输出。您可以看到延迟扩展不再处于活动状态,并且不再定义测试:

C:\test>CtrlCTest
test=AFTER sub SETLOCAL

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

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

C:\test>

您可以将:ExitBatch例程放在驻留在PATH中某个位置的独立ExitBatch.bat脚本中,然后任何批处理都可以根据需要方便地调用该实用程序。

@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

答案 3 :(得分:1)

您可以将错误级别与退出代码一起使用,如下所述:http://www.robvanderwoude.com/errorlevel.php

特别是,如果你想做一个手动错误,那么c.bat或b.bat应明确指定一个用

指定的退出代码
EXIT /b 1

(或你选择的一些),但是如果你只是想要计算windows自动错误,那么在运行b.bat或c.bat后,你就可以写了

IF ERRORLEVEL 1 EXIT /b %ERRORLEVEL%

将相同的错误传播到下一个程序,因此如果您愿意,可以立即退出。有一个优点,你可以随时停止向上传播。

(编辑:要清楚,除了底层程序之外,这里提到的第二行代码是必要的,无论你是否使用手动或自动错误)

答案 4 :(得分:0)

如果.BAT文件在TakeCommand下,请使用CANCEL。