从另一个批处理文件中批处理中调用子例程

use*_*634 3 batch-file

file1.bat:

@echo off
 :Test
echo in file one
call file2.bat (Here i want to call only Demo routine in the file2.bat)
Run Code Online (Sandbox Code Playgroud)

file2.bat:

:hello
echo in hello
:Demo
 echo in Demo
Run Code Online (Sandbox Code Playgroud)

我想从批处理文件1中调用批处理文件2中的子例程。
我尝试了例如,call file2.bat:Demo但是没有给出正确的结果。

我该如何实现?

npo*_*aka 6

带有子程序的文件必须如下所示:

@echo off
call :%*
exit /b %errorlevel%

:hello
echo in hello
exit /b 0
:Demo
 echo in Demo with argument %1
 exit /b 0
Run Code Online (Sandbox Code Playgroud)

然后从另一个文件中,您可以像这样称呼它

call file2.bat demo "arg-one"
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢将 GOTO 与 SHIFT 而不是 CALL 一起使用,因为 CALL 使 % 加倍、有毒字符转义和插入符号加倍的问题复杂化。 (2认同)

MC *_* ND 5

您可以将函数文件(在此示例中为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
Run Code Online (Sandbox Code Playgroud)

然后,呼叫者批次可以像

@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 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,需要在两个文件中使用相同的名称定义标签。

直接调用“库”批处理文件将替换的上下文call :label,并且在读取所调用的批处理时,将goto :label在内部执行a并在指示的标签内继续执行代码。当被调用的批处理文件结束时,将释放上下文,并call :label继续执行之后的代码。

已编辑

正如Jeb在评论中指出的那样,这种方法有一个缺点。在被调用的批处理文件中运行的代码不能用于%0检索被调用函数的名称,它将返回该批处理文件的名称。但是,如果需要,调用者可以按照示例代码中所示进行操作。

编辑2016/12/27

回答dbenham,我无法知道这是编码错误还是预期的功能,但这是该过程的工作方式

BatLoop创建批处理“上下文”时,批处理文件中的行将在内部函数中进行处理。此函数作为其参数之一接收指向导致创建“上下文”的命令的指针。

在此功能内,批处理文件中的命令被迭代。遍历命令的循环在每次迭代中进行测试:如果启用了扩展,则它是批处理文件中的第一行,并且启动上下文的命令的参数以冒号(标签)开头,将goto生成一个跳转到标签。

到这里为止,我必须假设这是处理call :label语法的预期行为:创建一个新的“上下文”,加载文件,跳转到标签。

但是收到的命令参数永远不会改变,使用另一个变量来跟踪批处理文件中命令的执行。如果将新的批处理文件加载到/覆盖当前的批处理“上下文”(我们尚未使用call命令),则在加载新的批处理代码后,将BatLoop重置行数(我们从已加载文件的第一行开始),瞧,则循环开始处的条件(允许扩展,第一行,冒号)再次为真(指向的输入命令尚未更改),并goto生成新的条件。

  • 我喜欢这个技巧,只有一个小_drawback_,在辅助批处理`%0`的被调用函数中不包含函数名,而是包含批处理文件名,但是几乎没有人使用`%0`来检索当前函数。名称,这是一个很小的差异 (2认同)
  • 隐式的GOTO可以任意深度链接。library.cmd中的函数可以执行library2.cmd(无CALL),而library2.cmd也将执行GOTO。我想知道此功能是否故意?我无法想象为什么除非设计人员想要此功能,否则每次启动新脚本时都会缓存并执行GOTO。两种方式都很酷。 (2认同)