调用Windows.bat时,ECHO是打开还是关闭?

1qczuiv0  于 2022-11-30  发布在  Windows
关注(0)|答案(4)|浏览(217)

当我从一个Windows .bat文件CALL另一个Windows .bat文件时,被调用的文件是否可以告诉ECHO在调用者中是ON还是OFF
当输入.bat文件时,ECHO被设置为ON(即使在CALLER中它是OFF)。
我想在被调用的.bat中保留调用方的ECHOstatus,这样我就可以从一个地方控制两者(可能是两个以上嵌套调用的链)。
我可以传递一个参数或者设置我自己的环境变量,但是有没有更好的方法?

编辑只是为了说明需要什么:cmd只需要在运行期间关闭回显。2在返回到调用者时,它必须恢复调用者的回显状态。

请填写以下脚本中的?????s:
callee.cmd:

@rem save the echo state
@ ???? HOW???? ????
@ set "savedEchoState=??????"

@rem the following commands must not be echoed
@echo off
command1
command2
command3

@rem restore the previous echo state
echo %savedEchoState%

caller1.cmd:

@echo off
call callee.cmd
echo

caller2.cmd:

@echo on
call callee.cmd
echo

所需输出:
caller1.cmd必须打印echo off,而caller2.cmd必须打印echo on

不需要在磁盘上创建任何文件就能完成吗?

laximzn5

laximzn51#

这是一个困难的问题。所有涉及管道或for的操作都不起作用,因为会生成新的进程,从而使echo状态无效。可能涉及临时文件:
A.BAT:

echo on
echo
call b.bat
echo off
echo
call b.bat
echo

B.BAT:

@(>tmp echo)
@type tmp|find "ON" >nul && (@set "oldEcho=ON") || (@set "OldEcho=OFF")
@echo off
echo B:echo was previously %OldEcho%
REM insert your payload here
REM restore previous Echo Status:
echo %OldEcho%

结果:

C:\Folder>a

C:\Folder>echo on

C:\Folder>echo
ECHO ist eingeschaltet (ON).

C:\Folder>call b.bat
B:echo was previously ON

C:\Folder>echo off
ECHO ist ausgeschaltet (OFF).
B:echo was previously OFF
ECHO ist ausgeschaltet (OFF).
xeufq47z

xeufq47z2#

要检测ECHO状态而不依赖于Windows语言,您可以使用临时文件。
当ECHO为OFF时,该文件为空,否则它包含ECHO IS ON的语言字符串。

@echo off
echo Testing detectEchoState

echo on
@call :detectEchoState

@echo off
@call :detectEchoState off
exit /b

:detectEchoState
@(
    (
        FOR /F %%L in ("1") do REM
    ) > "%TEMP%\echoCheck.tmp"

    FOR /F "delims=" %%F in ("%TEMP%\echoCheck.tmp") do @if %%~zF == 0 (set "EchoState=OFF" ) ELSE (set "EchoState=ON")
    del "%TEMP%\echoCheck.tmp"
    echo EchoState !EchoState!
)
@exit /b

Win10的解决方案,不需要建立档案(需要vt100)

@echo off

for /F "delims=#" %%a in ('prompt #$E# ^& for %%a in ^(1^) do rem') do set "ESC=%%a"

echo OFF
@call :get_echo_state
@echo state=%state%

echo ON
@call :get_echo_state
@echo state=%state%
@exit /b

:get_echo_state
@(
    setlocal EnableDelayedExpansion
    <nul set /p "=%ESC%7%ESC%[1H"
    set "prompt=%ESC%["
    set "0=call "
    for %%a in (1) do !0!
    <nul set /p "=%ESC%[6n%ESC%8"
    endlocal
) > CON
@(
    set "state=on"
    pause < con > NUL
    pause < con > NUL
    for /F "tokens=1 skip=1 eol=" %%C in ('"replace /w /u ? . < con"') do @(
        if "%%C" == "1" @set "state=off"
    )
    exit /b
)

这将使用ansi转义序列将光标移动到第1行。
当 *echo关闭 * 时,光标不会改变,否则会移到下一行。
然后,程式码会读取游标的行号,并还原原始的游标位置。
状态仅取决于检索到的行号。

2ul0zpep

2ul0zpep3#

我也遇到了同样的问题,最后出现在这个页面上。
下面是jeb脚本的一个稍微改进的版本。

  • 它使用(call,)而不是rem,这样就不必将)放在单独的行中。
  • 它并不取决于测试时打开的延迟膨胀。
@echo off
call :TestEchoState off
call :TestEchoState on
exit /b

:TestEchoState %1=ON or OFF
echo %1
@echo
@call :GetEchoState STATE
@echo off
echo STATE=%STATE%
exit /b

:GetEchoState %1=OUTVAR
@for /f %%F in ("%TEMP%\EchoState%PID%.tmp") do @(
  (FOR /f %%N in ("1") do call,) > "%%F"
  for %%S in ("%%F") do @if %%~zS==0 (set "%1=OFF") else (set "%1=ON")
  del "%%F"
)
@exit /b

如果您接受只测试errorlevel,则可以使检测例程更短:

@echo off
call :TestEchoLevel off
call :TestEchoLevel on
exit /b

:TestEchoLevel %1=ON or OFF
echo %1
@echo
@call :GetEchoLevel
@echo off
if errorlevel 1 (echo STATE=ON) else (echo STATE=OFF)
exit /b

:GetEchoLevel # Returns errorlevel 0 if echo is off
@for /f %%F in ("%TEMP%\EchoLevel%PID%.tmp") do @(
  (for /F %%N in ("1") do call,) > "%%F"
  for %%S in ("%%F") do @del "%%F" & exit /b %%~zS
)
gg58donl

gg58donl4#

(编辑Stephan的答案,考虑到回声状态也可以用小写报告,并且他的答案不允许编辑。)
下面的前两行和最后一行保存和恢复回显状态。第3行到第6行应该替换为您的代码:

@(>tmp echo)
@type tmp|find /i "ON" >nul && (@set "oldEcho=ON") || (@set "OldEcho=OFF")
    @echo off                               &::line 3
    echo B:echo was previously %OldEcho%    &::line 4
    REM insert your payload here            &::line 5
    REM restore previous Echo Status:       &::line 6
echo %OldEcho%

相关问题