2016-07-21 65 views
5

Próbuję zarejestrować wyjście net stop, a także przechwycić jego ERRORLEVEL.ERRORLEVEL w FOR/F Pętla sterująca zwraca nieoczekiwany wynik

podstawie this question próbowałem następujące od wewnątrz podprogramu zagnieżdżonego:

set /a loopIndex=0 
for /F "usebackq delims=" %%i in (`net stop %SERVICE_NAME%`) do (
if !loopIndex! EQU 0 if !errorlevel! EQU 1 set statementError=1 
set /a loopIndex+=1 
call :logMessage "%%i" 
) 
echo statementError: %statementError% 

Jednak to nie działa, rzucając 1 nawet gdy net stop powiedzie.

Czy jest to możliwe bez pliku tymczasowego? Jeśli nie, jak będzie wyglądało rozwiązanie pliku tymczasowego?

+0

ERRORLEVEL nie jest zmienną środowiskową. Nie musi być otoczony przez% lub! 'IF ErrorLevel 1' działa poprawnie. –

+0

Przeczytaj ponownie połączony wpis. * Oprócz tego stanu wewnętrznego, ** możesz, jeśli chcesz, utworzyć zmienną środowiskową o nazwie ERRORLEVEL **, w ten sam sposób, w jaki możesz utworzyć zmienną środowiskową o nazwie FRED. Ale tak jak w przypadku FRED, zmienna ta nie będzie miała żadnego wpływu na poziom błędu. * (** podkreślenie moje **). –

+1

@KenWhite 'ERRORLEVEL' * to * automatyczna zmienna środowiskowa, podobnie jak' CD', 'DATA' lub' RANDOM'. – dxiv

Odpowiedz

2

Podczas użytkownika @ dbenham answer nadaje się do przypadków, w których %ERRORLEVEL% powraca do wartości binarnej, nie był w stanie stwierdzić, czy nie zaprzecza zwrócone kody wyprowadzeniem net stop w rzeczywistości binarne i tak zdecydował się roztworu n-ary.

Zgodnie @ dbenham na DOS tips forum post:

FOR /F "delims=" %%i IN ('net stop MyService 2^>^&1 ^& CALL ECHO %%^^ERRORLEVEL%%^>error.level') DO (
CALL :logMessage "%%i" 
) 
FOR /F "delims=" %%i IN (error.level) DO (SET /A statementError=%%i) 
DEL error.level 
IF %statementError% NEQ 0() 

Przełamywanie parsowania oświadczenie:

net stop MyService 2^>^&1 ^& CALL ECHO %%^^ERRORLEVEL%%^>error.level 
net stop MyService 2>&1 & CALL ECHO %^ERRORLEVEL%>error.level 
echo %ERRORLEVEL%>error.level 

Tutaj CALL jest używany specjalnie do opóźnienia analizowania składni %ERRORLEVEL% do czasu wykonania ECHO.

+0

Ponieważ plik 'error.level' zawiera tylko jedną linię, można go odczytać jak' set/P statementError = "" <"error.level" 'lub, w przypadku, gdy plik może nie istnieć lub być pusty,' set "statementError = 0" & set/P statementError = "" <"error.level" 2> nul' ... – aschipfl

2

Polecenie FOR/F wykonuje NET STOP w nowym procesie cmd.exe. FOR/F przetwarza standardowe wyjście, ale to wszystko. W głównym skrypcie nie ma możliwości zobaczenia wartości zmiennych, które może utworzyć polecenie FOR/F, ponieważ zniknęły one po zakończeniu podprocesu.

Najprostsze i najbardziej wydajne rozwiązania wykorzystują plik tymczasowy. Zakładam, że NET STOP ma dwa możliwe kody błędów - Success = 0 i Error = 1. Najprostszym rozwiązaniem jest po prostu utworzenie tymczasowego pliku z sygnałem błędu, jeśli wystąpił błąd.

Poniższa pokazuje koncepcję w sposób ogólny:

@echo off 
del error.flag 2>nul 
for /f "delims=" %%A in ('net stop %SERVICE_NAME% ^|^| echo error>error.flag') do (
    ... 
) 
if exist error.flag (
    echo There was an error 
    del error.flag 
) 

Mogłeś równie dobrze umieścić test błędu wewnątrz Do() kodu w razie potrzeby.