• 【批处理DOS-CMD命令-汇总和小结】-CMD窗口的设置与操作命令-关闭cmd窗口、退出cmd环境(exit、exit /b、goto :eof)


    一、对exit命令和goto命令的基本认知

    打印exit命令的帮助信息,执行命令【exit /?】。

    1. C:\Users\Administrator>exit /?
    2. 退出 CMD.EXE 程序(命令解释器)或当前批处理脚本。
    3. EXIT [/B] [exitCode]
    4. /B 指定要退出当前批处理脚本而不是 CMD.EXE。如果从一个
    5. 批处理脚本外执行,则会退出 CMD.EXE
    6. exitCode 指定一个数字号码。如果指定了 /B,将 ERRORLEVEL
    7. 设成那个数字。如果退出 CMD.EXE,则用那个数字设置
    8. 过程退出代码。

    打印goto命令的帮助信息,执行命令【goto /?】。

    1. C:\Users\Administrator>goto /?
    2. 将 cmd.exe 定向到批处理程序中带标签的行。
    3. GOTO label
    4. label 指定批处理程序中用作标签的文字字符串。
    5. 标签必须单独一行,并且以冒号打头。
    6. 如果命令扩展被启用,GOTO 会如下改变:
    7. GOTO 命令现在接受目标标签 :EOF,这个标签将控制转移到当前
    8. 批脚本文件的结尾。不定义就退出批脚本文件,这是一个容易的
    9. 办法。有关能使该功能有用的 CALL 命令的扩展描述,请键入
    10. CALL /?。

     

    二、3种命令和各种执行情况

    从上面的帮助信息,我们也可以了解到,如果不考虑exit指令的exitcode,那么一共有3种退出cmd窗口或者批处理脚本程序(子程序)的方法,分别是【exit】、【exit /b】、【goto :eof】。

    但是,上面3种方法对应的3条指令,在各个位置(情况)执行的结果却大有不同。

    下面这张思维导图,尽可能列举了各种有几率存在差异的情况。

    看上去一共有14种情况,但其实有一些情况在测试过程中表现出明显的同一性,可以划等号(绿色箭头连接),而叠加环境的情况在bat文件中完全无影响。详见后续的7.1.1-7.1.3。

    在此直接给出简化的测试思维导图,直接用【双击执行bat】代替用【cmd窗口执行bat】,直接用【call调用脚本内部子程序】代替【call外部调用】,直接用【不叠加环境】执行脚本。

    2.1 双击执行bat和在cmd窗口执行bat相同

    (1)对exit的测试

    在【D:\D-desktop】目录下新建一个main.bat文件,代码如下

    1. @echo off
    2. chcp 65001
    3. echo "主程序开始执行"
    4. echo "下一条指令调用demo"
    5. call D:\D-desktop\demo.bat
    6. pause

    再在同一目录新建一个demo.bat文件,代码如下

    1. @echo off
    2. echo "子程序开始执行"
    3. echo "下一条执行exit"
    4. exit
    5. echo "子程序的exit执行完了"

    直接双击执行main.bat,cmd窗口打开的瞬间又闪退。

    而在手动打开的cmd窗口中执行main,这个手动打开的cmd窗口也闪退。

     (2)对exit /b的测试

     在【D:\D-desktop】目录下新建一个main.bat文件,代码如下。

    1. @echo off
    2. chcp 65001
    3. echo "主程序开始执行"
    4. echo "下一条指令调用demo"
    5. call D:\D-desktop\demo.bat
    6. pause

    再在同一目录新建一个demo.bat文件,代码如下。

    1. @echo off
    2. echo "子程序开始执行"
    3. echo "下一条执行exit /b"
    4. exit /b
    5. echo "子程序的exit /b执行完了"

    直接双击执行main.bat,cmd窗口打开后,能正常输出,值得注意的是【echo "子程序的exit /b执行完了"】并没有输出,因为执行【exit /b】后就退出demo.bat程序了。

    而在手动打开的cmd窗口中执行main,这个手动打开的cmd窗口也输出了和上面【双击执行】一样的结果。

    (3)对goto :eof的测试

     在【D:\D-desktop】目录下新建一个main.bat文件,代码如下。

    1. @echo off
    2. chcp 65001
    3. echo "主程序开始执行"
    4. echo "下一条指令调用demo"
    5. call D:\D-desktop\demo.bat
    6. pause

    再在同一目录新建一个demo.bat文件,代码如下。

    1. @echo off
    2. echo "子程序开始执行"
    3. echo "下一条执行goto :eof"
    4. goto :eof
    5. echo "子程序的goto :eof执行完了"

    直接双击执行main.bat,cmd窗口打开后,能正常输出,值得注意的是【echo "子程序的goto :eof执行完了"】并没有输出,因为执行【goto :eof】后就退出demo.bat程序了。

    而在手动打开的cmd窗口中执行main,这个手动打开的cmd窗口也输出了和上面【双击执行】一样的结果。

     

    2.2 call调用脚本内子程序和call调用外部脚本相同

    2.2.1 对exit的测试

    2.2.2 对exit /b的测试

    2.2.3 对goto :eof的测试

    (1)先测试【call调用脚本内子程序】的情况~

    在【D:\D-desktop】目录下新建一个main.bat文件,代码如下。

    1. @echo off
    2. chcp 65001
    3. echo "主程序开始执行"
    4. echo "下一条指令调用demo"
    5. call:demo
    6. pause
    7. :demo
    8. echo "子程序开始执行"
    9. echo "下一条执行goto :eof"
    10. goto :eof
    11. echo "子程序的goto :eof执行完了"

    直接双击执行main.bat,cmd窗口打开后,能正常输出,值得注意的是【echo "子程序的goto :eof执行完了"】并没有输出,因为执行【goto :eof】后就退出demo.bat程序了。

    (2)接着测试【call调用外部脚本】的情况~

    在【D:\D-desktop】目录下新建一个main.bat文件,代码如下。

    1. @echo off
    2. chcp 65001
    3. echo "主程序开始执行"
    4. echo "下一条指令调用demo"
    5. call D:\D-desktop\demo.bat
    6. pause

    再在同一目录新建一个demo.bat文件,代码如下。

    1. @echo off
    2. echo "子程序开始执行"
    3. echo "下一条执行goto :eof"
    4. goto :eof
    5. echo "子程序的goto :eof执行完了"

    直接双击执行main.bat,cmd窗口打开后,能正常输出,值得注意的是【echo "子程序的goto :eof执行完了"】并没有输出,因为执行【goto :eof】后就退出demo.bat程序了。

    在前面直接给出简要的结论。

    【exit】。不管是在主程序中执行还是子程序(批处理脚本)中执行,不管是在程序的第几层执行,都会直接导致cmd窗口的退出。

    【goto :eof】。如果在脚本主程序中执行,就会立即退出脚本;如果在主脚本中调用子脚本时执行,会退出子脚本而继续向下执行上一层的脚本程序;如果在脚本内的子程序中执行,就会退出子程序而继续执行主程序。注意它不能用来退出环境,这一点只有exit和exit /b支持。

    【exit /b】。除了可以添加exitcode参数,还有必须在命令扩展打开的时候使用,以及在退出环境方面和exit效果近似,其他与【goto :eof】可以说完全相同。

    三、在cmd原生窗口中执行

    7.1.1 执行exit时——直接退出

    如果你是在cmd原生窗口中执行exit命令,意思就是说没有进入某种命令的环境,比如python环境、diskpart环境、命令扩展环境、扩展变量或延迟变量环境,那么cmd窗口会直接被关闭。

     7.1.2 执行exit /b时——无反应

     7.1.3 执行goto :eof时——无反应

    7.2 在命令环境下执行——退出环境 

    7.2.1 退出python环境——exit()

    假如我已经进入到了python环境,然后想返回到原生cmd环境中,直接执行exit()命令即可。

    如果执行exit,会出错的。 

    对于命令【exit /b】和命令【goto :eof】,出错更厉害!

    7.2.2 退出diskpart环境——exit或exit /b

    假如你在cmd窗口中执行diskpart命令进入对应环境中, 而后程序会自动弹出一个关于diskpart.exe的窗口。

    错误的返回原生cmd窗口的方式是单击diskpart.exe窗口右上角的“叉叉”,由于这样会导致原生Cmd窗口无法正常使用,后续只能重开。

      

    正确的返回cmd原生环境的方式应该是在diskpart.exe窗口中执行exit命令。

     

    对于命令【exit /b】,也是能用来退出diskpart环境的。

     命令【goto :eof】却无法退出diskpart环境。

    7.2.3 退出命令扩展环境——exit或exit /b

    当我们在原生CMD窗口中执行命令【cmd /e:on】时,标题后面就新加了一串命令文字,这其实就属于叠加了一层cmd环境(命令扩展环境)。

    我们可以用exit命令来一层一层地退出cmd环境。

     

     进入扩展变量环境后,执行命令【goto :eof】没反应,说明不能用来退出环境。

    进入扩展变量环境后,执行命令【exit /b】有反应(见蓝色圈圈),说明可用来退出环境。

    7.2.4 退出延迟变量环境——exit或exit /b

    在cmd原生窗口中执行命令【cmd /v:on】(或命令【cmd /v)来打开延迟变量环境,同样标题栏也会多一串命令字符。

    如果要退出这层环境,也可以用exit退出。

    进入扩展变量环境后,执行命令【goto :eof】没反应,说明不能用来退出环境。

    进入扩展变量环境后,执行命令【exit /b】有反应(见蓝色圈圈),说明可用来退出环境。

    其他的cmd环境,可以在cmd /?中查看,退出的方法都是执行命令【exit】,我就不再赘述了。

    7.3 脚本内call调用子程序来执行exit

    7.3.1 内部调用执行exit直接退出或在环境中失效

    (1)直接退出cmd窗口的情况

    当你在脚本文件中,没有启动或打开任何的环境,那么执行exit命令的瞬间就会直接关闭cmd窗口。

    如下代码,复制进一个bat文件后双击执行,发现cmd窗口闪退。

    1. @echo off
    2. echo main1.bat start to execute!
    3. call :end
    4. pause
    5. :end
    6. echo subprogram is executeing!
    7. exit

    显然,是在调用子程序时,执行了子程序的【exit】才退出cmd窗口的,没来得及执行主程序的Pause命令。 

    (2)cmd系列命令不建议在脚本文件使用

    假如我略加修改一下上面(1)的代码,添加一层cmd环境(扩展变量环境),就不会闪退了。

    原因倒并不是因为叠加了一层环境后,执行exit命令是退出环境;原因在于叠加了一层环境后,所有的命令都失效了,包括exit命令。 

    1. @echo off
    2. echo main1.bat start to execute!
    3. cmd /v
    4. call :end
    5. pause
    6. :end
    7. echo subprogram is executeing!
    8. exit

     

    7.3.2 外部调用执行exit跟内部调用情况一样

    之所以在标题中说是情况一样,是因为在叠加环境时,下面的指令也会失效。

    而如果不叠加环境,一旦执行exit命令,cmd窗口也会闪退。

    测试代码如下。

    main.bat的代码。

    1. @echo off
    2. chcp 65001
    3. echo "主程序开始执行"
    4. echo "下一条指令调用demo"
    5. cmd /v:on
    6. call D:\D-desktop\demo.bat
    7. echo "在子程序中执行exit之后,主程序call下面的代码都不执行"
    8. pause

    demo.bat的代码。

    1. @echo off
    2. chcp 65001
    3. echo "在脚本文件中,一旦进入了cmd环境,就不能再echo任何内容"
    4. echo "所以子程序的所有输出都被忽略了"
    5. echo "子程序开始执行"
    6. echo "下一条执行exit"
    7. exit
    8. echo "子程序的exit执行完了"
    9. echo "对于exit后面的代码,显然不执行了"

    双击执行,结果如下 。

    我们显然也可以看到,只要执行了【cmd /v:on】,下面的代码都失效了。

    而比较惊奇的另一点,虽然主程序最后一行的pause命令失效,但是执行bat脚本文件时也没出现闪退。

    而如果把进入环境的指令去掉,就又会出现闪退问题,估计是因为exit命令又生效了。

    所以,你们知道为啥我在7.3.1的某标题说不要在批处理脚本中执行类似【cmd /e:on】、【cmd /v:on】的命令了吧?因为cmd开发人员可能压根就没想着我们用户在这里用。

    因为有专门的批处理脚本命令【setlocal ENABLEEXTENSIONS】和【setlocal ENABLEDELAYEDEXPANSION】我们却不用,四不四傻?

    另外,根据我测试这么久的经验,发现只要使用call命令调用,不管是调用本脚本内的子程序还是调用外部脚本,结果都一样,因此后面只进行其中一种测试。

    7.4 在cmd窗口中执行bat程序

    在cmd窗口中执行bat脚本程序,情况和上面的7.3完全一样。

    也是执行命令【cmd /v:on】后,下面的指令全部失效(包括exit);如果没进入cmd环境时,执行exit会直接关闭cmd窗口。

    如下所示,如果代码最后一行有exit,并且exit之前没有进入环境,就直接退出当前cmd窗口。

    1. @echo off
    2. chcp 65001
    3. echo "main1.bat开始执行"
    4. echo "下一条执行exit命令"
    5. exit

    如下所示,在Exit前加一行环境激活命令,那么exit就不会生效,但缺点也很明显,其他该生效的也失效了。

    1. @echo off
    2. chcp 65001
    3. echo "main1.bat开始执行"
    4. cmd /v:on
    5. echo "下一条执行exit命令"
    6. exit

  • 相关阅读:
    双线路捆绑
    Java内存模型基础(JMM)
    notepad++中文出现异体汉字,怎么改正
    神经网络——循环神经网络(RNN)
    【PyTorch深度学习项目实战100例】—— 基于Transformer实现人格个性指示 | 第67例
    回溯--字母迷宫
    【羊了个羊】背后的计算机网络原理
    手把手教你在ARM板上写一个驱动程序!
    Ubuntu20运行SegNeXt代码提取道路水体(一)——从零开始运行代码过程摸索
    C专家编程 第9章 再论数组 9.6 C语言的多维数组
  • 原文地址:https://blog.csdn.net/PSpiritV/article/details/125564843