file1.bat:
@echo off
:Test
echo in file one
call file2.bat (Here i want to call only Demo routine in the file2.bat)
file2.bat:
:hello
echo in hello
:Demo
echo in Demo
从批处理文件1中我想调用批处理文件2中的子程序
我尝试过例如call file2.bat:Demo
,但它没有给出正确的结果。
我怎么能做到这一点?
答案 0 :(得分:4)
子程序的文件必须如下所示:
@echo off
call :%*
exit /b %errorlevel%
:hello
echo in hello
exit /b 0
:Demo
echo in Demo with argument %1
exit /b 0
然后从另一个文件中你可以称之为
call file2.bat demo "arg-one"
答案 1 :(得分:4)
您可以将函数文件(在此示例中为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
之后的代码。
<强>编辑强>
正如杰布在评论中指出的那样,这种方法存在缺陷。在被调用批处理文件中运行的代码不能使用%0
来检索被调用函数的名称,它将返回批处理文件的名称。但是如果需要,调用者可以执行它,如示例代码所示。
编辑2016/12/27
回答dbenham,我无法知道这是编码错误还是预期的功能,但这是过程的工作原理
批处理&#34;上下文&#34>批处理文件中的行在内部BatLoop
函数内处理。被建造。该函数作为其参数之一接收指向导致&#34; context&#34;的命令的指针。要被创造。
在此函数中,迭代批处理文件中的命令。循环遍历命令的循环在每次迭代中进行测试:如果启用了扩展,则它是批处理文件中的第一行,并且启动上下文的命令的参数以冒号(标签)开头,{{生成1}}以跳转到标签。
到目前为止,我必须假设这是处理goto
语法的预期行为:创建一个新的&#34; context&#34;,加载文件,跳转到标签。
但是收到的命令参数永远不会改变,另一个变量用于跟踪批处理文件中命令的执行。如果将新批处理文件加载到/覆盖当前批处理&#34; context&#34; (我们没有使用call :label
命令),在加载新批处理代码后,call
重置行数(我们从加载文件的第一行开始),瞧,开始时的条件循环(已启用扩展,第一行,冒号)再次为真(指向的输入命令尚未更改)并生成新的BatLoop
。
答案 2 :(得分:0)
要多评论一下,这是我阅读答案得到的代码。它基本上为您提供了一个“实用程序”文件,您可以在其中将sub / fnc添加到公共库中进行代码维护。
A)例如,这是'utility_sub.cmd'文件:
REM ==============================================
REM CALL THE SELECTED SUB
REM ==============================================
REM echo %~1
GOTO :%~1
REM ==============================================
REM ERROR MANAGEMENT
REM ==============================================
REM Ref : https://ss64.com/nt/exit.html
:RAISE_ERROR
EXIT /B 1
:RESET_ERROR
EXIT /B 0
REM Demo call
REM =========
REM CALL :RAISE_ERROR
REM echo RAISE_ERROR ERRORLEVEL = %ERRORLEVEL%
REM If %ERRORLEVEL% GTR 0 (
REM set msg="%tab%- Error detected ..."
REM CALL :SUB_STDOUT_MSG !msg!, 1
REM )
REM CALL :RESET_ERROR
REM echo RESET_ERROR ERRORLEVEL = %ERRORLEVEL%
REM ==============================================
REM SUB_STDOUT_MSG
REM ==============================================
:SUB_STDOUT_MSG
REM CALL :SUB_STDOUT_MSG "%param1%", %param2%, %param3%
REM Instead of this stdout sub, we can use Unix 'tee.exe'
REM but there is no 'line counter' feature like this sub
REM Call example :
REM EDI_Generate_Stat_Csv | tee c:\temp\voir.txt
REM Def :
REM Capture output from a program and also display the output to the screen, at the same time.
REM %~1 => Expand %1 removing any surrounding quotes (")
set msg=%~2
set sendtoLog=%3
set addCounter=%4
If !msg!==. (
REM Write empty line
echo!msg!
If !sendtoLog! EQU 1 (
echo!msg! >> %log_file%
)
) else (
REM (a) Write comment line (b) add counter if any
If !addCounter! EQU 1 (
set /a msgCounter+=1
set msg=!msgCounter! - !msg!
REM Pad counter left for single digit
If !msgCounter! LSS 10 (
set msg=0!msg!
)
)
REM Output to console
echo !msg!
REM Output to log
If !sendtoLog! EQU 1 (
echo !msg! >> %log_file%
)
)
EXIT /B
B)以下是在“主逻辑”命令文件中调用“ SUB_STDOUT_MSG”的方法:
REM ... some other code here
REM ==============================================
REM PROGRAM END
REM ==============================================
set msg=.
CALL :SUB_STDOUT_MSG !msg!, 1
set msg="My programA - End"
CALL :SUB_STDOUT_MSG !msg!, 1
set msg="%date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%:%time:~3,2%:%time:~6,2%"
CALL :SUB_STDOUT_MSG !msg!, 1
set msg="+++++++++++++++"
CALL :SUB_STDOUT_MSG !msg!, 1
timeout 2 > Nul
REM Skip all SUB ROUTINE
GOTO :EOF
REM ==============================================
REM CALL SUB ROUTINE
REM ==============================================
:SUB_STDOUT_MSG
REM echo calling sub %0
CALL "C:\Utilitaires\Financement\Utility_Sub.cmd" SUB_STDOUT_MSG %*
EXIT /B
:EOF
答案 3 :(得分:0)
如何提供目标标签作为被调用脚本的第一个要素?不过您需要修改被调用的dscript。
file1.bat
(主要):
@echo off
echo/
echo File "%~0": call "file2.bat" [no arguments]
call "file2.bat"
echo/
echo File "%~0": call "file2.bat" :DEMO
call "file2.bat" :DEMO
echo/
echo File "%~0": call "file2.bat" :DEMO A B C
call "file2.bat" :DEMO A B C
file2.bat
(子):
@echo off
set "ARG1=%~1" & if not defined ARG1 goto :TEST
if "%ARG1:~,1%"==":" goto %ARG1%
:TEST
echo File "%~nx0", :TEST; arguments: %*
goto :EOF
:DEMO
echo File "%~nx0", :DEMO; arguments: %*
echo before `shift /1`:
echo "%%~0" refers to "%~0"
echo "%%~1" refers to "%~1"
shift /1
echo after `shift /1`:
echo "%%~0" refers to "%~0"
echo "%%~1" refers to "%~1"
goto :EOF
输出:
>>> file1.bat File "file1.bat": call "file2.bat" [no arguments] File "file2.bat", :TEST; arguments: File "file1.bat": call "file2.bat" :DEMO File "file2.bat", :DEMO; arguments: :DEMO before `shift /1`: "%~0" refers to "file2.bat" "%~1" refers to ":DEMO" after `shift /1`: "%~0" refers to "file2.bat" "%~1" refers to "" File "file1.bat": call "file2.bat" :DEMO A B C File "file2.bat", :DEMO; arguments: :DEMO A B C before `shift /1`: "%~0" refers to "file2.bat" "%~1" refers to ":DEMO" after `shift /1`: "%~0" refers to "file2.bat" "%~1" refers to "A"