2009-06-01 18 views
6

Mam plik wsadowy okien, z kilkoma sub-rutyny w nim coś takiego:Jak zakończyć plik wsadowy systemu Windows z poziomu procedury "wywołania"?

call :a 
goto :eof 

:a 
call :b 
goto :eof 

:b 
:: How do I directly exit here from here? 
goto :eof 

biegnę to w cmd okna na Vista.
Jeśli wykryję błąd gdzieś w pliku wsadowym, chcę go zakończyć przy niezerowym poziomie błędu. Czy jest coś, co mogę napisać w procedurze: b, która spowoduje, że plik wsadowy zakończy się w ten sposób.

  • Próbowałem "exit", który zamyka całe okno cmd. Nie tego chcę.
  • Próbowałem "exit/B 1". To powraca do poprzedniej procedury. Aby użyć tego schematu po każdym "wywołaniu", musiałbym ostrożnie napisać "jeśli poziom błędu 1 wyjście/B 1" po każdym pojedynczym "wywołaniu", aby przekazać błąd, z powrotem do stosu wywołań. Wolałbym nie pisać tej linii po każdym wywołaniu.

Ten artykuł był interesujący, ale żadne z alternatyw nie zachowuje się tak, jak chcę. http://www.computerhope.com/exithlp.htm

Czy istnieje inny sposób?

Dzięki.

Odpowiedz

14

możesz zadzwonić do podprogramów tak:

call :b||exit /b 1 

co jest równoważne

call :b 
if errorlevel 1 exit /b 1 

To nieco krótsza i zaoszczędzić jedną linię, ale wciąż nie jest idealny, zgadzam się.

Poza tym nie widzę sposobu.

EDIT: Dobra, mam sposób, ale to Pure Evil ™.

Nadużywanie maksymalny rozmiar stosu, a zatem ograniczenie rekursji, tworzymy inny podprogram, który po prostu wyczerpuje stos przez rekurencyjnie nazywająca siebie:

@echo off 
echo Calling a 
call :a 
echo Called a 
goto :eof 
:a 
echo Calling b 
call :b 
echo Called b 
goto :eof 
:b 
echo Trying to exit 
call :exit 
goto :eof 
:exit 
call :exit 

To jednak spowoduje paskudny komunikat o błędzie

 
****** B A T C H R E C U R S I O N exceeds STACK limits ****** 
Recursion Count=704, Stack Usage=90 percent 
******  B A T C H PROCESSING IS A B O R T E D  ****** 

Ponadto zajmie to około 2 sekund na moim komputerze.

Można wyłączyć komunikat o błędzie zmieniając oświadczenie call następująco:

call :exit >nul 2>&1 

który przekieruje wszystko, co chce wyjścia do wielkiej pustce.

Ale biorąc pod uwagę czas potrzebny do wypełnienia stosu, myślę, że pierwszy wariant będzie łatwiejszy.

Rozważałem także użycie drugiego pliku wsadowego, który po uruchomieniu bez call zasadniczo zatrzymałby pierwszy. Ale jakoś to nie gra dobrze z podprogramami. Odtworzenie stosu wywołań nadal ma miejsce.

+4

Fajnie, dzięki. To jest jak dotąd najlepsze. Z tego dowiedziałem się, że jeśli użyję "call: a || goto: eof", poziom błędu będzie propagowany z powrotem. Przydatne, jeśli określony poziom błędu ma pewne znaczenie użytkowe. –

+0

Tak, to brzmi naprawdę lepiej. Nie myślałem o tym. Również rekursywne przerwanie I opisane nie jest realną opcją, tak przypuszczam :) – Joey

+0

Tak, rekursywne przerwanie było powieścią, ale tylko trochę za daleko! :) –

0

Można utworzyć plik exit.bat, który zabije najwyższy plik bat według nazwy tytułu.

przykład:

A.bat

@echo off 
title A.bat 
echo A.bat 
call B.bat 
echo A.bat 

B.bat

@echo off 
echo B.bat 
exit.bat A.bat 
echo B.bat 

Exit.bat

@echo off 
echo exit.bat 
kill %1 
+1

będąc zdecydowanie chłodnym i zdecydowanie złym, to podejście pozbędzie się całego procesu cmd. Dokładnie to, co zrobiłby koniec, a którego OP nie uznał za zadowalający. Ponadto, kill musiałby zostać zastąpiony przez taskkill/fi "windowtitle -eq% 1", ponieważ nie ma polecenia kill w systemie Windows. – Joey

+0

Ah Zapomniałem, że zainstalowałem "Narzędzie do debugowania dla Windows" (WinDbg) i zawiera ono kopię programu kill.exe. Dzięki za polecenie taskkill, nie zdawałem sobie sprawy, że tam jest. –

+0

Aby sprawić, by ból zabijania całego okna był mniej bolesny, zawsze możesz użyć cmd a.bat, aby wystrzelić część, którą chcesz zabić. –

Powiązane problemy