您可以将函数文件(在此示例中为library.cmd)编写为
@echo off
setlocal enableextensions
rem Not to be directly called
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
在这种情况下,标签需要在两个文件中定义为相同的名称。
“库”批处理文件的直接调用将替换call :label 的上下文,当读取调用的批处理时,会在内部执行goto :label,代码在指示的标签内继续。当被调用的批处理文件结束时,上下文被释放,call :label之后的代码继续执行。
已编辑
正如 Jeb 在 cmets 中指出的那样,这种方法有一个缺点。在被调用的批处理文件中运行的代码不能使用%0 来检索被调用函数的名称,它将返回批处理文件的名称。但如果需要,调用者可以按照示例代码所示进行。
于 2016 年 12 月 27 日编辑
回答dbenham,我无法知道这是编码错误还是预期的功能,但这就是过程的工作方式
当创建批处理“上下文”时,批处理文件中的行在内部BatLoop 函数中进行处理。该函数接收作为其参数之一的指向导致创建“上下文”的命令的指针。
在这个函数中,批处理文件中的命令被迭代。遍历命令的循环在每次迭代中进行测试:如果启用了扩展,则它是批处理文件中的第一行,并且启动上下文的命令的参数以冒号(标签)开头,@987654330生成@ 以跳转到标签。
到这里为止,我不得不假设这是处理call :label 语法的预期行为:创建一个新的“上下文”,加载文件,跳转到标签。
但是收到的命令参数永远不会改变,一个不同的变量用于跟踪批处理文件中命令的执行。如果一个新的批处理文件被加载到/覆盖当前批处理“上下文”(我们没有使用call命令),在加载新的批处理代码后,BatLoop重置行数(我们从第一行开始加载的文件),瞧,循环开始的条件(启用扩展,第一行,冒号)再次为真(指向的输入命令未更改)并生成新的goto。