8

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

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

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

一只蝙蝠

@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”。关于如何退出嵌套批处理文件的任何想法?

4

5 回答 5

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
()
于 2013-07-15T13:42:00.837 回答
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。它使用一种令人惊讶的技术以编程方式“按下”Ctrl-C,我在为什么非交互式批处理脚本认为我按下了 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

这是示例运行输出。您可以看到延迟扩展不再有效,并且不再定义测试:

C:\test>CtrlCTest
test=AFTER sub SETLOCAL

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

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

C:\test>

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

@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
于 2014-08-24T18:46:00.520 回答
2

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

特别是,如果你想做一个手动错误,那么 c.bat 或 b.bat 应该明确地指定一个退出代码

EXIT /b 1

(或您选择的数字),但如果您只想计算 Windows 自动错误,那么在运行 b.bat 或 c.bat 之后,您可以编写

IF ERRORLEVEL 1 EXIT /b %ERRORLEVEL%

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

(编辑:需要明确的是,这里提到的第二行代码在除底层程序之外的所有程序中都是必需的,无论您使用的是手动错误还是自动错误)

于 2013-07-15T13:45:40.950 回答
2

你可以试试这个(c.bat):

@echo. this is batch 'c'
@pause
exit
于 2013-07-15T13:38:39.773 回答
0

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

于 2015-08-02T06:37:07.067 回答