In a DOS Batch File subroutine, how can I turn off echo within the subroutine, but before returning, put it back to what it was before (either on or off)?
For example, if there was a command called echo restore
, I would use it like this:
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
The simplest way is to not turn echo off in the first place.
Instead, do what you currently do with the echo off
line to the rest of your subroutine - prefix all commands in the subroutine with an @
sign. This has the effect of turning off echo for that command, but keeps the echo state for future commands.
If you use commands that execute other commands, like IF or DO, you will also need to prefix the "subcommand" with an @ to keep them from being printed when echo is otherwise on.
My first attempt was an utter failure - thanks jeb for pointing out the errors. For those that are interested, the original answer is available in the edit history.
Aacini has a good solution if you don't mind putting your subroutine in a separate file.
Here is a solution that works without the need of a 2nd batch file. And it actually works this time! :)
(Edit 2 - optimized code as per jeb's suggestion in comment)
: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
)
If you are willing to put up with the slight risk of two processes simultaneously trying to access the same file, the :getEchoState routine can be simplified without the need of SETLOCAL or a temp variable.
: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
)
The easiest way is to extract the subroutine to another .bat file and call it via CMD /C
instead of CALL
this way:
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
This way the echo status will be automatically restored to the value it had when the CMD /C
was executed; the only drawback of this method is a slightly slower execution...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With