Jak zapobiec zamykaniu wiersza polecenia po wykonaniu?

54

Mój problem polega na tym, że w systemie Windows istnieją okna wiersza polecenia, które zamykają się natychmiast po wykonaniu. Aby rozwiązać ten problem, chcę, aby domyślnym zachowaniem było pozostawienie otwartego okna. Zwykle tego zachowania można uniknąć za pomocą trzech metod, które przychodzą mi na myśl:

  1. Umieszczanie pausewiersza po programach wsadowych w celu poproszenia użytkownika o naciśnięcie klawisza przed wyjściem
  2. Uruchamianie tych plików wsadowych lub innych narzędzi do manipulowania wierszem poleceń (nawet uruchamianie, restartowanie itp. Za pomocą net start xylub coś podobnego) w cmd.exe(Start - Run - cmd.exe)
  3. Uruchamianie tych programów w cmd /knastępujący sposób: cmd /k myprogram.bat

Ale są też inne przypadki, w których użytkownik:

  1. Uruchamia program za pierwszym razem i nie wie, że dany program będzie działał w wierszu polecenia (Windows Command Processor), np. Podczas uruchamiania skrótu z menu Start (lub z innego miejsca) LUB
  2. Trochę niewygodne jest uruchamianie cmd.exe przez cały czas i nie ma czasu / możliwości przepisania kodu tych poleceń wszędzie, aby po nich zatrzymać lub uniknąć jawnego wyjścia.

Przeczytałem artykuł o zmianie domyślnego zachowania cmd.exepodczas otwierania go jawnie, z tworzeniem wpisu AutoRun i manipulowaniem jego zawartością w tych lokalizacjach:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor\AutoRun
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Command Processor\AutoRun

(Elementy AutoRun są _String values_...)

Podaję cmd /d /kjako wartość, aby spróbować, ale to wcale nie zmieniło zachowania wyżej wymienionych rzeczy ... Po prostu zmieniło zachowanie okna wiersza poleceń podczas jawnego otwierania (Start-Run- cmd.exe).

Jak to działa? Czy możesz podać mi pomysły na rozwiązanie tego problemu?

Sk8erPeter
źródło
10
Twoje pytanie z wszystkimi wyjaśnieniami sprawiło, że moja głowa chciała eksplodować. Czy możesz powiedzieć coś w stylu: Chcę uruchomić plik wsadowy za pomocą tego polecenia „przykład” i chcę, aby okno poleceń pozostało otwarte po zakończeniu. Czy o to pytasz? Dodaj dokładną próbkę kodu.
KCotreau
1
+1 uzgodnione. Trochę do sformułowania, proszę ponownie rozważyć swoje pytanie i, jeśli to możliwe, użyć przykładu i sformułować bardziej zwięzłe pytanie.
slotishtype
2
Jest to normalne zachowanie i chociaż twoje pytanie jest z pewnością prawidłowe, powinieneś zadawać sobie pytanie, dlaczego musisz pozostawić otwarty wiersz polecenia (większość narzędzi jest tworzona z myślą o tym zastrzeżeniu).
Przełom
1
Moim zdaniem nie jest to prawdziwe pytanie. Ponieważ po prostu instruujesz użytkownika, aby zamiast tego używał pliku wsadowego. Jeśli nie jest to celem pytania, wyjaśnij swoje pytanie, usuwając wszelkie mylące informacje i wyjaśnij, jaki jest twój prawdziwy cel. Trudno jest znaleźć właściwą odpowiedź, jeśli jest niejasna ...
Tamara Wijsman
1
@Randolf Richardson, to dlatego, że te narzędzia nie powinny być postrzegane przez użytkownika końcowego w historii (po wszystkim, dlatego teraz używać GUI). Jeśli potrzebujesz takich informacji, większość grup IT wyśle ​​pliki wsadowe, aby zebrać odpowiednie informacje systemowe i wyświetlić je. Nie widzę żadnego możliwego sposobu, aby znalezienie rozwiązania tego problemu spowodowało mniej problemów niż rozwiązanie - tyle rzeczy wysyłanych jest stdoutna bieżąco, które nigdy nie powinny być widoczne z dobrego powodu.
Przełom

Odpowiedzi:

27

Mam rozwiązanie, które można zastosować tylko .cmdi .batpliki:

Otwórz regediti przejdź do każdego z:

[HKEY_CLASSES_ROOT\batfile\shell\open\command]
[HKEY_CLASSES_ROOT\cmdfile\shell\open\command] 

Teraz zmień „Domyślną wartość klucza” na cmd.exe /k "%1" %*. Teraz każde okno skryptu wsadowego pozostanie otwarte po jego wykonaniu.

Zauważ, że jest to jak używanie cmd.exe /c cmd.exe /k program.bat, co oznacza, że ​​inna instancja CMD zostanie uruchomiona w instancji nadrzędnej. Nie mogłem znaleźć sposobu na zastąpienie pierwszego /cargumentu.

Możesz to również zrobić za pomocą [exefile], ale teraz pokaże puste pole konsoli, jeśli plik wykonywalny ma GUI.

not2qubit
źródło
4
+1 za posiadanie jedynego rozwiązania, które faktycznie odpowiada na zadane pytanie. Niestety myślę, że może to być wyciek pamięci, który czeka. Co się stanie, gdy usługa uruchomi nowy plik wsadowy bez podawania CMD.EXE w wierszu CMD? Czy ten kod nie będzie używany w takim przypadku? Czy to nie spowoduje utworzenia nowego okna na nieinteraktywnym pulpicie i pozostawienia go otwartego do ponownego uruchomienia?
krowe2
@APerson Twoja edycja złamała polecenie, nie włączając *. Zachowaj ostrożność podczas edycji!
not2qubit
@ not2qubit Przepraszamy, nie zauważyłem, że usunąłem trzy gwiazdki zamiast dwóch. Zrobi.
APerson
17

Cytuj Microsoft :

Konsola jest zamykana, gdy ostatni dołączony do niej proces kończy się lub wywołuje FreeConsole.

Innymi słowy, okno konsoli Win32 będzie zawsze zamknięte, gdy ostatni program w nim zamknięty, i nie można tego zmienić.


(W przypadku 16-bitowych programów MS-DOS system Windows oferuje opcję „Zamknij przy wyjściu” w oknie dialogowym właściwości, ale nie jest to wyjątek od powyższego zachowania: proces NTVDM utrzymuje okno otwarte. Ponadto ta opcja jest ponownie na program).

grawitacja
źródło
13
+1 za zrozumienie, w jaki sposób i dlaczego zamykają się okna konsoli (w przeciwieństwie do większości, którzy po prostu mówią „OMG DLACZEGO NIE MOŻNA OTWORZYĆ !!!!!!!!!!! 1111one”). Zachowuje się zgodnie z przeznaczeniem i tak powinno pozostać IMHO. Jest to główny powód, dla którego mamy przede wszystkim standardowe strumienie i pliki wsadowe.
Przełom
27
@Breakthrough Pytanie brzmi How can I do X, nie In your opinion, should I do X. Ta odpowiedź jest nieprzydatna, oznacza, że ​​X jest niemożliwy, gdy częściowe rozwiązania zostały już przedstawione gdzie indziej. (-1)
Superbest
7

Wystarczy otworzyć wiersz polecenia w lokalizacji pliku wsadowego i ręcznie wprowadzić nazwę pliku wsadowego, aby uruchomić go w tym oknie.

1. Przejdź do folderu, w którym znajduje się plik wykonywalny
2. Kliknij prawym klawiszem Shift i wybierz „Okno poleceń stąd”
3. wpisz nazwę pliku wykonywalnego i naciśnij klawisz Enter
4. Proces powinien się uruchomić, ale okno powinno pozostać otwarte

Lee Harrison
źródło
1
Nie wiedziałem o Shift + kliknięciu prawym przyciskiem myszy. Możesz jednak również przeciągnąć plik exe do okna cmd, które automatycznie wstawi ścieżkę dla Ciebie.
Superbest
1
Zwykle działa to dla mnie, ale najwyraźniej nie jest to pewne, ponieważ szukam rozwiązania właśnie dlatego, że nie działa w mojej obecnej sytuacji.
RenniePet,
jest to najłatwiejsze rozwiązanie i musi być oznaczone jako poprawna odpowiedź
Vicky Kapadia
4

cmd.exe /ksprawi ci kłopot z jakąś partią. Jeśli partia exit 1(bez /B) konsola zostanie zamknięta. Sztuką jest użycie:

cmd.exe /k cmd /c ...

Aby używać tego domyślnie dla wszystkich plików wsadowych, ustaw HKEY_CLASSES_ROOT\cmdfile\shell\open\command\(default)i HKEY_CLASSES_ROOT\batfile\shell\open\command\(default)na "%windir%\system32\cmd.exe" /k "%windir%\system32\cmd" /c "%1" %*.

Wernight
źródło
1
Pomyślałem, że "%*"przekazuje pełną listę parametrów, więc czy pierwszy parametr nie przejdzie dwa razy, raz za "%1"razem jako pierwszy parametr "%*"?
Kevin Fegan
1
@KevinFegan Nie sprawdziłem powodu, ale% 1 powinien zachować cytaty, co oznacza, że ​​w niektórych przypadkach może być podwójnie cytowany. Istnieje również różnica pomiędzy %1 %2 %3 ..i %*które nie pamiętam w tej chwili, ale w %1 %2 %3pracach w niektórych przypadkach, gdy %*nie powiedzie się.
Wernight
3

Właśnie przeczytałem głupie rozwiązanie po przeczytaniu grawityodpowiedzi.

Moim przypadkiem użycia było skonfigurowanie środowiska konsoli w pracy, w którym wszystkie bardziej rozsądne rozwiązania są blokowane. Wszystko, czego potrzebuję, to ustawić PATH i skonfigurować aliasy doskey i zostać zrzuconym do powłoki.

Moje rozwiązanie (właśnie przetestowane na Win7) jako dodane cmdjako ostatni wiersz w pliku wsadowym. Spowoduje to uruchomienie zagnieżdżonego wiersza polecenia, który dziedziczy środowisko swojego elementu nadrzędnego. Ta powłoka potomna utrzymuje proces wsadowy otwarty aż do WYJŚCIA, w którym to momencie partia nie ma procesów potomnych, a także kończy działanie.

kitsu.eb
źródło
2

Zamiast używać PAUZY (wolę WYBÓR lub CZAS, niż w razie potrzeby używać PAUZY), możesz skorzystać z rozwiązania tutaj: 886848 / how-to-make-windows-batch-file-pause-when-double-click .

W ten sposób, jeśli klikniesz plik wsadowy lub łącze (skrót) w Eksploratorze Windows, możesz wstrzymać program pliku wsadowego przed wyjściem, aby wyświetlić wyniki programu i wszelkie komunikaty o błędach.

Korzystając z WYBORU, możesz zaprogramować możliwość wyboru przez użytkownika różnych działań, a użycie TIMEOUT może pozwolić na zamknięcie okna po pewnym czasie (bez nadzoru). Jeśli plik wsadowy zostanie uruchomiony z poziomu okna wiersza polecenia, te przerwy mogą być denerwujące.

Połączone rozwiązanie pozwoli Ci zdecydować, czy chcesz pominąć przerwy, jeśli plik wsadowy został uruchomiony z okna wiersza polecenia.

Możesz przeczytać więcej pod podanym linkiem, ale jego podstawą jest to, że używa zmiennej środowiskowej:

%cmdcmdline%

aby ustalić, czy plik wsadowy został uruchomiony z okna poleceń, czy nie.

Używasz go w ten sposób:

W miejscu, w którym plik wsadowy zostanie zamknięty, dodajesz taki kod:

echo %cmdcmdline:"=-% | find /i "cmd /c --%~dpf0%-"
if %errorlevel% NEQ 0 goto :EOF
pause
goto :EOF

rem if %errorlevel% EQU 0 batch-file: %~dpf0 was executed from Windows Explorer, ...
rem if %errorlevel% NEQ 0 batch-file: %~dpf0 was executed from within a Command Prompt
Kevin Fegan
źródło
1

Najlepszym sposobem na obejście tego problemu jest wywołanie plików wsadowych z innego pliku wsadowego przy użyciu polecenia Start.

więc jeśli normalnie uruchamiasz plik o nazwie go.bat, utworzyłbyś drugi plik wsadowy o nazwie coś takiego jak go2.bat

zawartość go2.bat byłaby po prostu

start go.bat

pierwsze okno zamyka się natychmiast, ale to, w którym uruchomiono go.bat, pozostaje otwarte

agradl
źródło
Działa, po prostu umieściłem nazwę pliku wiersza polecenia w jednym pliku nietoperza (1.bat), który jest wywoływany za pomocą polecenia start z drugiego pliku nietoperza „start 1.bat”. Okno poleceń pozostaje otwarte.
ejectamenta
1

Działa to w przypadku wersji 5.00 Edytora rejestru systemu Windows.

[HKEY_CLASSES_ROOT\batfile\shell\open\command]
@="cmd.exe /k \"%1\" %*"

[HKEY_CLASSES_ROOT\cmdfile\shell\open\command]
@="cmd.exe /k \"%1\" %*"

Zapisz powyższe polecenia cmd w pliku o nazwie coś podobnego cmdbatfile-open.regi uruchom je!

VumC
źródło
2
Witamy w Stack Exchange! Poprawiłem formatowanie w twojej odpowiedzi dla ciebie. Zobacz tutaj, aby uzyskać pomoc dotyczącą formatowania. Ponadto, kiedy piszesz kod, pamiętaj o wyjaśnieniu, co dokładnie robi. Możesz także przeczytać instrukcje dotyczące odbierania .
Blacklight Shining
1

Załóżmy, że masz dwa pliki wsadowe, które chcesz uruchomić we własnej instancji i pozostaną otwarte, jeśli ich plik wykonywalny zostanie zamknięty. Nazwijmy te dwie partie A.bati B.bat.

Teraz dla uproszczenia możesz mieć plik wsadowy, aby uruchomić je oba, nazwijmy to launch_both.batz zawartością:

start cmd /k "A.bat & cmd /c"
start cmd /k "B.bat & cmd /c"

Może nie działać zgodnie z oczekiwaniami, jeśli wywołasz exitjeden z dwóch plików wsadowych. To będzie wymagało przetestowania.

Francois
źródło
0

W przypadku użytkowników systemu Windows 10 zauważ, że żadna z powyższych odpowiedzi nie działa obecnie w systemie Windows 10.

W przypadku systemu Windows 10, jeśli masz dostęp do skryptu, musisz dodać następujący kod na końcu:

read

Ten kod będzie czekał na dane wejściowe przed zamknięciem.

jaycode
źródło
Pamiętaj, że pytanie zostało zadane przed Windows 10 (5 lat temu), edytuj swoją odpowiedź, podając więcej informacji
yass
0

W odpowiedzi na obniżoną wersję PSIXO - „Ta odpowiedź została już ujęta w pytaniu. - Ro Yo Mi Jan 20 '16 o 5:06” - NIE, NIE była. Poprzednie odpowiedzi brzmiały: „pauza”, która NIE działała. Odpowiedź PSIXO brzmiała: „& pauza”, która DZIAŁA. Proszę przeanalizować ostrożniej przed obniżeniem oceny. Uruchomiłem to z wiersza IDLE i zadziałało:

    >>> os.system('dir ^ & pause')
    0
    >>> 

Z drugiej strony:

    >>> os.system('dir ^ pause')
    1
    >>>

NIE działało (polecenie cmd prześlizgnęło się i faktycznie zwróciło błąd (1)). Dzięki PSIXO za odpowiedź, której potrzebowałem. Henz.

Henz
źródło