2012-03-06 115 views
7

在DOS批處理文件子程序中,如何關閉子程序中的回聲,但在返回之前,將其恢復到以前的狀態(打開或關閉)?恢復以前的回聲狀態

例如,如果有一個叫做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 

回答

2

最簡單的方法是不轉擺在首位呼應關

相反,做你目前做的echo off線子程序的其餘部分 - 與@符號前綴子程序中的所有命令。這具有關閉該命令的回聲的效果,但是爲將來的命令保留回聲狀態。

如果您使用執行其他命令(如IF或DO)的命令,則還需要在「子命令」前加上@來防止回顯時打印它們。

5

我的第一次嘗試是徹底的失敗 - 謝謝jeb指出錯誤。對於那些感興趣的人,原始答案在編輯歷史中可用。

如果您不介意將子程序放在單獨的文件中,Aacini有一個很好的解決方案。

這是一個解決方案,不需要第二個批處理文件。而且這次真的有用! :)

(編輯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或temp變量。

: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 
) 
+2

不錯的想法,但它不能工作!由於'for/f「標記中的'echo'= 3 delims =。」%% A('echo')中的A將在新的cmd-context中執行並始終爲'ON'。第二個問題是,即使你得到的狀態是本地化的,就像我的系統一樣,我得到了'ECHO ist eingeschaltet(ON)'。' – jeb 2012-03-07 08:09:20

+0

當然你是對的,該死的:)最糟糕的是,我已經發現了所有這很久以前(德國問題除外),並忘記了!我會想出一個工作版本。 – dbenham 2012-03-07 12:38:18

+0

您可以使用重定向'echo> tmpfile.tmp',然後使用FOR循環。也許最後一個標記總是ON/OFF或(ON)/(OFF) – jeb 2012-03-07 12:43:27

3

最簡單的方法是給子程序提取到另一個.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執行時的值ED;這種方法的唯一缺點是執行速度稍慢...

+0

請檢查我的編輯 – JoelFan 2012-03-07 14:21:00

1

這是一個直接的解決方案,它依賴於一個臨時文件(使用%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

我一直在尋找同樣的解決同樣的問題,看完之後你的意見我有一個想法(這不是問題的答案,但對我的問題更好)。

我不滿意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變體(或開始)。 它也有,我們可以保留或放棄標準錯誤加,與>nul 2>&1

更換>nul我注意到,ss64.com scares孩子們喜歡我,說明具有呼叫「重定向與& | <>也不會因爲工作預計「。 這個簡單的測試按預期工作。他一定在想更復雜的情況。

1

由於語言問題,我對上述解決方案並不滿意,只是通過將當前回顯設置的結果與顯式設置爲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