восстановить предыдущий статус эха - PullRequest
7 голосов
/ 07 марта 2012

В подпрограмме DOS Batch File, как я могу отключить эхо в подпрограмме, но перед возвратом верните его к тому, что было раньше (включено или выключено)?

Например, если естьбыла команда с именем echo restore, я бы использовал ее так:

echo on
... do stuff with echoing ...
call :mySub
... continue to do stuff with echoing ...
exit /b

:mySub
@echo off
... do stuff with no echoing ...
echo restore
goto :EOF

Ответы [ 6 ]

5 голосов
/ 07 марта 2012

Моя первая попытка была полным провалом - спасибо, Джеб, за указание на ошибки.Для тех, кто заинтересован, оригинальный ответ доступен в истории редактирования.

У Aacini есть хорошее решение, если вы не против поместить свою подпрограмму в отдельный файл.

Вотрешение, которое работает без необходимости 2-го пакетного файла.И это действительно работает на этот раз!:)

(Редактировать 2 - оптимизированный код в соответствии с предложением Джеба в комментарии)

:mysub
::Silently get the echo state and turn echo off
@(
  setlocal
  call :getEchoState echoState
  echo off
)
::Do whatever
set return=returnValue
::Restore the echo state, pass the return value across endlocal, and return
(
  endlocal
  echo %echoState%
  set return=%return%
  exit /b
)

:getEchoState echoStateVar
@setlocal
@set file=%time%
@set file="%temp%\getEchoState%file::=_%_%random%.tmp"
@(
  for %%A in (dummy) do rem
) >%file%
@for %%A in (%file%) do @(
  endlocal
  if %%~zA equ 0 (set %~1=OFF) else set %~1=ON
  del %file%
  exit /b
)

Если вы готовы смириться с небольшим риском одновременного доступа двух процессов к одному и тому жефайла, процедура: getEchoState может быть упрощена без необходимости использования SETLOCAL или временной переменной.

:getEchoState echoStateVar
@(
  for %%A in (dummy) do rem
) >"%temp%\getEchoState.tmp"
@for %%A in ("%temp%\getEchoState.tmp") do @(
  if %%~zA equ 0 (set %~1=OFF) else set %~1=ON
  del "%temp%\getEchoState.tmp"
  exit /b
)
4 голосов
/ 07 марта 2012

Самый простой способ - извлечь подпрограмму в другой файл .bat и вызвать ее через CMD /C вместо CALL следующим образом:

echo on
... do stuff with echoing ...
cmd /C mySub
... continue to do stuff with echoing ...
exit /b

mySub.bat:

@echo off
... do stuff with no echoing ...
exit /b

Таким образом, состояние эха будет автоматически восстановлено до значения, которое оно имело при выполнении CMD /C;единственный недостаток этого метода - немного более медленное выполнение ...

2 голосов
/ 07 марта 2012

Самый простой способ - это , во-первых, не отключать эхо .

Вместо этого делать то, что вы в настоящее время делаете со строкой echo off для остальной части вашей подпрограммы - префиксвсе команды в подпрограмме со знаком @.Это приводит к отключению echo для этой команды, но сохраняет состояние echo для будущих команд.

Если вы используете команды, которые выполняют другие команды, такие как IF или DO, вам также потребуется префикс «подкоманды»"с @, чтобы не печатать их, когда эхо включено.

1 голос
/ 25 сентября 2015

Мне не очень понравилось вышеприведенное решение, особенно из-за языковой проблемы, и я нашел очень простую, просто сравнив результат текущей настройки эха с результатом, когда явно установлено значение OFF.Вот как это работает:

::  SaveEchoSetting
::  :::::::::::::::::::::::::::
::  Store current result    
@echo>  %temp%\SEScur.tmp

::  Store result when explicitly set OFF
@echo   off
@echo>  %temp%\SESoff.tmp

::  If results do not match, it must have been ON ... else it was already OFF
@for /f "tokens=*" %%r in (%temp%\SEScur.tmp) do (
    @find   "%%r" %temp%\SESoff.tmp > nul
    @if     errorlevel 1 (
        @echo   @echo on > %temp%\SESfix.bat
    ) else (
        @echo   @echo off > %temp%\SESfix.bat
    )
)

::  
::  Other code comes here
::  Do whatever you want with echo setting ...
::

::  Restore echo setting
@call   %temp%\SESfix.bat
1 голос
/ 26 августа 2012

Вот прямое решение, которое опирается на один временный файл (использование% random%, чтобы избежать условий гонки).Он работает и, по крайней мере, устойчив к локализации , т. Е. Работает для двух известных случаев, указанных @JoelFan и @ jeb.

@set __ME_tempfile=%temp%\%~nx0.echo-state.%random%.%random%.txt
@set __ME_echo=OFF
@echo > "%__ME_tempfile%"
@type "%__ME_tempfile%" | @"%SystemRoot%\System32\findstr" /i /r " [(]*on[)]*\.$" > nul
@if "%ERRORLEVEL%"=="0" (set __ME_echo=ON)
@erase "%__ME_tempfile%" > nul
@::echo __ME_echo=%__ME_echo%
@echo off
...
endlocal & echo %__ME_echo%
@goto :EOF

Добавьте этот предварительный код, чтобы повысить надежность решения.(хотя странность высока, что в этом нет необходимости):

@:: define TEMP path
@if NOT DEFINED temp ( @set "temp=%tmp%" )
@if NOT EXIST "%temp%" ( @set "temp=%tmp%" )
@if NOT EXIST "%temp%" ( @set "temp=%LocalAppData%\Temp" )
@if NOT EXIST "%temp%" ( @exit /b -1 )
:__ME_find_tempfile
@set __ME_tempfile=%temp%\%~nx0.echo-state.%random%.%random%.txt
@if EXIST "%__ME_tempfile%" ( goto :__ME_find_tempfile )
0 голосов
/ 04 декабря 2013

Я искал такое же решение той же проблемы, и после прочтения ваших комментариев у меня возникла идея (которая не является ответом на вопрос, но для моей проблемы еще лучше).

Я не был удовлетворен cmd.exe /c mysub.cmd, потому что он затрудняет или даже делает невозможным возвращение переменных (я не проверял) - (не могу комментировать, потому что я впервые публикую здесь:)

Вместо этого заметил, что все, что мы хотим - в конце концов - подавить стандартный вывод:

echo on

rem call "mysub.cmd" >nul
call :mysub >nul

echo %mysub_return_value%

GOTO :eof 

:mysub
    setlocal
    set mysub_return_value="ApplePie"
    endlocal & set mysub_return_value=%mysub_return_value%
GOTO :eof

Он отлично работает с помеченными подпрограммами, с подпрограммами, содержащимися в файлах .cmd, и я полагаю, что он будет работать нормально даже с вариантом cmd.exe / c (или start). Он также имеет плюс, который мы можем оставить или отбросить, заменив >nul на >nul 2>&1

Замечу, что ss64.com пугает дети, подобные мне, заявляют, что с вызовом "Перенаправление с & | <> также не работает должным образом" . Этот простой тест работает, как и ожидалось. Должно быть, он думал о более сложных ситуациях.

...