【问题标题】:To "Call" or "Not to Call" a batch file?要“调用”或“不调用”批处理文件?
【发布时间】:2013-01-21 19:36:21
【问题描述】:

如果您从一个 bat 文件中调用了另一个批处理文件,但仍有一些剩余操作要完成,您如何确保对第一个 bat 文件的调用在完成或出错后将返回到调用它的文件一开始?

例子:

CD:\MyFolder\MyFiles
Mybatfile.bat

Copy afile toHere

CD:\MyFolder\MyFiles
CALL Mybatfile.bat

COPY afile toHere

使用CALLSTART 或根本不使用它们有什么区别?这会对它是否返回复制命令的结果有任何影响吗?

【问题讨论】:

标签: batch-file cmd command-line call


【解决方案1】:

正如其他人所说,CALL 是在 .bat 中调用另一个 bat 文件并返回给调用者的正常方式。

但是,如果 CALLed 批处理文件有致命的语法错误,或者如果 CALLed 脚本在没有 /B 选项的情况下以 EXIT 终止,则所有批处理文件处理都将停止(控制权不会返回给调用者)。

如果您通过 CMD 命令执行第二个脚本,您可以保证控制权将返回给调用者(当然,只要控制台窗口保持打开状态)。

cmd /c "calledFile.bat"

但这有一个限制,即被调用的批处理设置的环境变量在返回时不会被保留。

我不知道有什么好的解决方案可以保证在所有情况下都返回并保留环境变化。

如果您在使用 CMD 时确实需要保留变量,那么您可以让“被调用”脚本将变量更改写入临时文件,然后让调用者读取临时文件并重新建立变量。

【讨论】:

  • 我发现以下页面对cmd /cCALL之间的区别颇有启发:robvanderwoude.com/call.php
  • 而且不管你call,start还是只运行第二个bat,第一个bat的所有环境变量set都可以被第二个bat使用。
【解决方案2】:

call 对于 .bat 或 .cmd 文件是必需的,否则控件将不会返回给调用者。
对于 exe 文件,它不是必需的。

Startcall 不同,它创建一个新的 cmd.exe 实例,因此它可以异步运行一个称为的批处理文件

【讨论】:

  • 我最近在工作中遇到了这个问题,从来不知道。 +1。
  • 不禁想,什么时候有人不使用 CALL 或 START - 当所有脚本返回时终止调用者脚本似乎很奇怪?
【解决方案3】:

“CALL”语句是在 MS-DOS 3.3 中引入的

用于在一个批处理文件中调用其他批处理文件,不中止调用批处理文件的执行,两个批处理文件使用相同的环境。

所以在你的情况下,解决方案是使用CALL

【讨论】:

    【解决方案4】:

    好吧,我实际上什至没有真正考虑过这样一个事实,即如果你调用一个批处理(无论是“类型”,即“.bat”或“.cmd”),如果你调用它,它就不会返回。不要使用通话。

    尽管出于不同的原因,我一直在使用自己的电话,但实际上我很惊讶没有其他人提出。也许我错过了。也许我是世界上唯一一个知道的人!! :O

    可能不会,但我将把这些知识放在这里,因为它非常有用。

    如果你使用 call 你可以使用二元逻辑运算符来决定如何根据 ERRORLEVEL 结果进行处理。事实上,我总是对 && 和 || 感到惊讶。存在于 DOS 中,不能以这种方式使用。嗯,这就是原因。

    最简单的测试方法是使用记事本创建return.cmd,或者像这样从命令提示符中创建:

    c:\> type con >return.cmd       
    

    您现在会注意到光标下降到下一行并挂起。输入:

    @exit /B %1
    

    然后按ENTER,然后按CTRL-Z,就会创建该文件。好的!您现在可以随意尝试以下两个示例:

    call return.cmd 0 && echo Huzzah! A Complete Success! (Or cover up...)

    call return.cmd 123 || echo Oops! Something happened. You can check ERRORLEVEL if you want the tinest amount of additional information possible.

    那又怎样?好吧,交换 0 和 123 再次运行它们,您应该会看到消息不会打印。

    也许这个多行示例会更有意义。我一直用这个:

         call return.cmd 0 && @(
             echo Batch says it completed successfully^^!
         ) || @(
             echo Batch completed, but returned a 'falsey' value of sort.
             call echo The specific value returned was: %ERRORLEVEL%
         )     
    

    (注意|| 部分中的第二个“回声”之前的“呼叫”。我相信这就是人们过去没有延迟扩展的方法。如果您确实启用了延迟扩展(通过。setlocal批处理中的 EnableDelayedExpansion 或使用 cmd /v:on 启动命令提示符,然后您可以执行 !ERRORLEVEL!。)

    ...这是我必须道歉的地方,如果你过去有过if ERRORLEVEL 创伤,你应该停止阅读。我知道了。相信我。我曾考虑在 Fiverr 上花钱请人为我远程输入此内容,但为了完整起见,我只想为团队拿一个,并提到您还可以执行以下操作来检查错误级别:

        if ERRORLEVEL 123 @echo QUICK! MOTHERS, COVER YOUR CHILDREN'S EYES! FINGERS ARE BEING UNDONE! :'(
    

    如果您之前从未输入过,那太好了!您将活得更久,而无需阅读为什么您没有得到您期望的结果。残酷是您要寻找的词,而不是“古怪”。


    然而,我真正想要了解的重要部分是,如果您尝试此操作并且不要使用“调用”,它将始终执行“真实”分支。自己试试吧!

    如果我遗漏了什么,或者您知道更好的方法,请告诉我。我喜欢学习这样的东西!


    我提到的其他信息:

    我早就知道你可以在命令之前放置重定向,如下所示:

        >nul echo. This won't be displayed!
    

    但前几天我无意中发现自己是个笨蛋,你显然也可以这样做:

        echo A B>file.txt C
    

    发现file.txt 由“A B C”组成,真的很惊讶。看来你可以把它们放在任何地方,甚至在命令里面。我从来没有见过有人这样做,也没有提到过,但我见过有人提到你可以在他们前面加上前缀。

    也许这是 Windows 10 独有的错误或其他问题。如果您有其他版本并想尝试一下,请告诉我,我会对您发现的内容感兴趣。

    保持书呆子!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 2015-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多