您可以编写函数文件(在此示例中为
library.cmd
)如下:
@echo off
setlocal enableextensions
exit /b 9009
:test
echo test [%*]
goto :eof
:test2
echo test2 [%*]
goto :eof
:testErrorlevel
echo testErrorlevel
exit /b 1
然后调用批处理可以是这样的
@echo off
setlocal enableextensions disabledelayedexpansion
call :test arg1 arg2 arg3
call :test2 arg4 arg5 arg6
call :testErrorlevel && echo no errorlevel || echo errorlevel raised
goto :eof
:test
:test2
echo calling function %0
library.cmd %*
:testErrorlevel
echo calling function %0
library.cmd
在这种情况下,标签需要在两个文件中使用相同的名称进行定义。
直接调用“library”批处理文件将替换
call:label
的上下文,当被调用的批处理文件被读取时,内部执行一个
goto:label
并继续在指定的标签内执行代码。当调用的批处理文件结束时,上下文被释放,并且在
call:label
之后的代码继续执行。
正如Jeb在评论中提到的那样,这种方法存在缺点。在调用的批处理文件中运行的代码无法使用
%0
检索被调用的函数的名称,它将返回批处理文件的名称。但是,如果需要,呼叫者可以按示例代码执行此操作。
回答dbenham,我无法确定是否是编码错误还是故意特性,但这就是进程如何工作。
处理批处理文件中的行时,它们被视为内部的
BatLoop
函数,创建批处理的“上下文”。此函数作为其参数之一接收导致创建“上下文”的命令的指针。
在此函数内部,对批处理文件中的命令进行迭代。迭代命令的循环在每次迭代中进行测试:如果启用扩展名,则它是批处理文件中的第一行,并且启动上下文的命令的参数以冒号(标签)开头,则生成
goto
以跳转到标签。
至此,我必须假设这是处理
call:label
语法的故意行为:创建一个新的“上下文”,加载文件,跳转到标签。
但是,接收到的命令参数从未更改,使用不同的变量来跟踪批处理文件中命令的执行。如果将新的批处理文件加载到/覆盖当前批处理“上下文”中(我们没有使用
call
命令),则在加载新的批处理代码后,
BatLoop
会重置行计数器(我们从已加载文件的第一行开始),并且条件在循环开始时(启用扩展名,第一行,冒号)再次成立(指向的输入命令未更改),并且会生成新的
goto
。