我曾经认为
setlocal
会创建一个新的作用域,这样 echo on/off
就不会泄漏到调用脚本。
鉴于
foo.cmd
:
@setlocal
@echo off
echo %0:A
echo
call bar.cmd
@REM cmd /c bar.cmd
echo %0:B
echo
和
bar.cmd
:
bar.cmd
@setlocal
@echo on
echo %0:C
echo
然后运行
foo.cmd
:
D:\src>foo.cmd
foo.cmd:A
ECHO is off.
D:\src>echo bar.cmd:C
bar.cmd:C
D:\src>echo
ECHO is on.
D:\src>echo foo.cmd:B
foo.cmd:B
D:\src>echo
ECHO is on.
从
call
切换到 cmd /c
可以获得所需的行为,但我想要一种编写 bar.cmd
的方法,即使使用 call
调用也不会修改调用者的回显状态。
希望得到更深入的解释和建议。
考虑线路
@FOR /f "tokens=3delims=. " %%s IN ('echo') DO @ECHO subprocedure entry state is %%s
您会发现,这会将
echo
状态报告为 ON
,无论调用者的 echo
状态如何,也无论该行是否是子过程的第一行或是否位于 @setlocal
行之后。
因此,我认为使用此方法不可能检测调用者的状态,但是
echo>filename
将生成一个包含
echo
状态的文件,所以
**主程序q78090799.bat **
@SETLOCAL
@ECHO OFF
FOR %%s IN (OFF ON) DO FOR %%u IN (OFF ON) DO @(
@ECHO %0:%%s
@ECHO %%s
@ECHO
@ECHO calling subprocedure with ECHO state %%s; s/p %%u
@CALL q78090799_2 %%u
@ECHO
@ECHO ===============================================
)
GOTO :EOF
子程序q78090799_2.bat
@SETLOCAL
@echo>"%temp%\#$"&FOR %%e IN ("%temp%\#$") DO @(IF %%~ze==13 (SET "echostate=on") ELSE (SET "echostate=off"))&@DEL "%temp%\#$"
@ECHO %1
@echo %0 runs with echo state %1
rem on exit, restore original state
@ECHO %echostate%
@GOTO :EOF
应使用局部变量
echostate
恢复原始状态,并且在退出子过程时执行 @ECHO %echostate%
至关重要。