Batch file how to call another batch file at a specified label or call and immediately goto a certain label?

前端 未结 5 1414
不知归路
不知归路 2021-01-02 00:57

I am trying to figure out how file1.bat can call file2.bat at a specified label.

I figured I can do it like this:

File1.bat

:config
         


        
5条回答
  •  情话喂你
    2021-01-02 02:03

    There are several methods or tricks that allows to do this. In this solution the trick consists in change the context of the running program to the second Batch file. After this change, all labels in the second Batch file becomes local labels of the running program, so they may be directly called via the usual call :label command that may also include arguments in an entirely standard way. The context of the running program must be recovered before the program terminates.

    The way to change the context consist is just rename the second Batch file with the same name of the first one (and rename the first one to any other name) so when the Batch file processor looks for a label, it really search the contents of the second file! The files must be renamed back to their original names before the program terminate. The key point that makes this method work is that both sets of rename commands (and all code between them) must be enclosed in parentheses; in this way, the code is first parsed and then executed from memory, so the rename of the files on disk don't affect it. Of course, this point means that the access to the values of all variables in the code must be done via delayed !expansion! (or using the call %%variable%% trick).

    First.bat

    @echo off
    
    rem Change the running context to the second/library batch file:
    (
    ren first.bat temporary.bat
    ren second.bat first.bat
    
    rem From this point on, you may call any label in second.bat like if it was a local label
    
    call :label2
    echo Returned from :label2
    call :label1
    echo Returned from :label1
    
    rem Recover the running context to the original batch file
    ren first.bat second.bat
    ren temporary.bat first.bat
    )
    
    echo This is first.bat ending...
    pause > nul
    

    Second.bat

    @echo off
    
    :label1
    echo I am label1 subroutine at second.bat
    goto :EOF
    
    :label2
    echo This is the second subroutine at second.bat
    goto :EOF
    

    OUTPUT

    This is the second subroutine at second.bat
    Returned from :label2
    I am label1 subroutine at second.bat
    Returned from :label1
    This is first.bat ending...
    

    You should note that this method allows to develop the subroutines in the first file in the usual way (with no context change) and then just move the completed subroutines to the second/library file, because the way to call them is exactly the same in both cases. This method does not require any change in the second/library file nor in the way the subroutines are called; it just needs to insert the two small blocks of rename commands in the first file.


    EDIT: Restoring files when a run-time error happen

    As indicated in a comment, if a run-time error happen after the files were renamed, the files are not renamed back to their original names; however, it is very easy to detect this situation by the presence of the second.bat file and restore the files if such a file does not exists. This test may be done in a supervisor section that run the original code in a separate cmd.exe context, so this section will always complete correctly even if the original code was cancelled by an error.

    First.bat

    @echo off
    
    if "%~1" equ "Original" goto Original
    
    rem This supervisor section run the original code in a separate cmd.exe context
    rem and restore the files if an error happened in the original code
    (
    cmd /C "%~F0" Original
    if not exist second.bat (
       echo Error detected!  Restoring files
       ren first.bat second.bat & ren temporary.bat first.bat
    )
    goto :EOF
    )
    
    
    :Original
    
    ( ren first.bat temporary.bat & ren second.bat first.bat
    
    call :label1
    echo Returned from :label1
    call :label2
    echo Returned from :label2
    
    ren first.bat second.bat & ren temporary.bat first.bat )
    
    echo This is first.bat ending...
    

    Second.bat

    @echo off
    
    :label1
    echo I am label1 subroutine at second.bat
    exit /B
    
    :label2
    set "var="
    if %var% equ X echo This line cause a run-time error!
    exit /B
    

    OUTPUT

    I am label1 subroutine at second.bat
    Returned from :label1
    No se esperaba X en este momento.
    Error detected!  Restoring files
    

提交回复
热议问题