¿Cómo evitar que el símbolo del sistema se cierre después de la ejecución?

55

Mi problema es que en Windows, hay ventanas de línea de comandos que se cierran inmediatamente después de la ejecución. Para resolver esto, quiero que el comportamiento predeterminado sea que la ventana se mantenga abierta. Normalmente, este comportamiento se puede evitar con tres métodos que me vienen a la mente:

  1. Poner una pauselínea después de los programas por lotes para solicitar al usuario que presione una tecla antes de salir
  2. Ejecutar estos archivos por lotes u otras herramientas de manipulación de línea de comandos (incluso el servicio de inicio, reinicio, etc. con net start xyo algo similar) dentro de cmd.exe(Inicio - Ejecutar - cmd.exe)
  3. Ejecutando estos programas con cmd /kesto: cmd /k myprogram.bat

Pero hay otros casos en los que el usuario:

  1. Ejecuta el programa la primera vez y no sabe que el programa en cuestión se ejecutará en el Símbolo del sistema (Procesador de comandos de Windows), por ejemplo, cuando ejecuta un acceso directo desde el menú Inicio (o desde otro lugar), O
  2. Le resulta un poco incómodo ejecutar cmd.exe todo el tiempo y no tiene el tiempo / la oportunidad de reescribir el código de estos comandos en todas partes para detenerlos o evitar salir explícitamente.

Leí un artículo sobre cómo cambiar el comportamiento predeterminado cmd.exeal abrirlo explícitamente, creando una entrada de ejecución automática y manipulando su contenido en estas ubicaciones:

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

(Los elementos de ejecución automática son _String values_...)

Lo puse cmd /d /kcomo valor para intentarlo, pero esto no cambió el comportamiento de las cosas mencionadas anteriormente en absoluto ... Simplemente cambió el comportamiento de la ventana de la línea de comandos al abrirla explícitamente (Start-Run- cmd.exe).

¿Entonces, cómo funciona? ¿Me puede dar alguna idea para resolver este problema?

Sk8erPeter
fuente
10
Su pregunta con todas las explicaciones hizo que mi cabeza quisiera explotar. ¿Puede decir algo como: Quiero ejecutar un archivo por lotes con este comando "ejemplo", y quiero que el cuadro de comando permanezca abierto cuando termine. ¿Eso es lo que está preguntando? Por favor, ponga una muestra cercana del código.
KCotreau
1
+1 de acuerdo. Un poco para detallar, reconsidere su pregunta y, si es posible, use un ejemplo y redacte una pregunta más sucinta.
slotishtype
2
Este es un comportamiento normal, y aunque su pregunta es válida, debería preguntarse por qué necesita mantener abierto el símbolo del sistema después (la mayoría de las utilidades se crean teniendo en cuenta esta advertencia).
Avance el
1
En mi opinión, esta no es una pregunta real. Como solo le indica al usuario que use un archivo por lotes en su lugar. Si esa no es la intención de la pregunta, aclare su pregunta eliminando cualquier información confusa y explique cuál es su objetivo real. Es difícil encontrar la respuesta correcta si no está claro ...
Tamara Wijsman
1
@Randolf Richardson, eso es porque esas herramientas no deben ser vistas por un usuario final (después de todo, es por eso que usamos GUI ahora). Si necesita dicha información, la mayoría de los grupos de TI enviarán archivos por lotes para recopilar la información adecuada del sistema y mostrarla. No puedo ver ninguna manera posible de que si se encuentra una solución a esta pregunta, causará menos problemas y luego se resuelve: se envían tantas cosas stdoutde manera constante que nunca debieron ser visibles por una buena razón.
Avance el

Respuestas:

27

Tengo una solución que solo se puede aplicar en .cmdy .batarchivos:

Abra regedity vaya a cada uno de:

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

Ahora cambie el "Valor clave predeterminado" a cmd.exe /k "%1" %*. Ahora, cada ventana de script por lotes permanecerá abierta después de su ejecución.

Tenga en cuenta que esto es como usar cmd.exe /c cmd.exe /k program.bat, lo que significa que se lanzará otra instancia de CMD en la instancia principal. No pude encontrar cómo sobrescribir el primer /cargumento.

También puede hacerlo con [exefile], pero ahora mostrará una caja de consola vacía si el ejecutable tiene una GUI.

not2qubit
fuente
44
+1 por tener la única solución aquí que realmente responde la pregunta dada. Desafortunadamente, creo que esto puede ser una pérdida de memoria esperando a suceder. ¿Qué sucede cuando un servicio lanza un nuevo archivo por lotes sin especificar CMD.EXE en la línea CMD? ¿No se usará este código en ese caso? ¿No va a crear una nueva ventana en un escritorio no interactivo y dejarlo abierto hasta que reinicie?
krowe2
@APerson Su edición rompió el comando al no incluir el *. ¡Ten más cuidado al editar!
not2qubit
@ not2qubit Lo siento, no noté que eliminé tres asteriscos en lugar de dos. Lo haré
APerson
17

Cita Microsoft :

Una consola se cierra cuando el último proceso adjunto termina o llama a FreeConsole.

En otras palabras, la ventana de la consola Win32 siempre se cerrará cuando salga el último programa que se ejecuta en su interior, y no puede cambiar esto.


(Para los programas de MS-DOS de 16 bits, Windows ofrece una opción "Cerrar al salir" en el cuadro de diálogo de propiedades, pero esto no es una excepción al comportamiento anterior: es el proceso NTVDM el que mantiene abierta la ventana. Además, esta opción es de nuevo por programa).

Gravedad
fuente
13
+1 para comprender cómo y por qué se cierran las ventanas de la consola (a diferencia de la mayoría de las personas que simplemente dicen "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡QUÉ NO PUEDE ESTAR ABIERTA !!! Se comporta según lo diseñado, y debería permanecer así en mi humilde opinión. Esta es la razón principal por la que tenemos secuencias estándar y archivos por lotes en primer lugar.
Avance el
27
@Breakthrough La pregunta es How can I do X, no In your opinion, should I do X. Esta respuesta no es útil, implica que X es imposible, cuando ya se han presentado soluciones parciales en otros lugares. (-1)
Superbest
8

Simplemente abra un símbolo del sistema en la ubicación de su archivo por lotes e ingrese manualmente el nombre de su archivo por lotes para ejecutarlo dentro de esa ventana.

1.Navegue a la carpeta donde reside su ejecutable
2.Haga clic con el botón derecho y seleccione "Ventana de comandos desde aquí"
3. escriba el nombre del ejecutable y presione enter
4.El proceso debe ejecutarse, pero la ventana debe permanecer abierta

Lee Harrison
fuente
1
No sabía sobre Shift + clic derecho. Además, sin embargo, puede arrastrar y soltar el exe en una ventana de cmd, que automáticamente coloca el camino por usted.
Superbest
1
Esto generalmente funciona para mí, pero aparentemente no es algo seguro porque estoy buscando una solución precisamente porque no funciona en mi situación actual.
RenniePet
esta es la solución más fácil y debe marcarse como la respuesta correcta
Vicky Kapadia
4

cmd.exe /kte dará problemas con algún lote. Si el lote exit 1(sin /B) su consola se cerrará. Un truco es usar:

cmd.exe /k cmd /c ...

Para usar esto de manera predeterminada para todos los archivos por lotes, configure HKEY_CLASSES_ROOT\cmdfile\shell\open\command\(default)y HKEY_CLASSES_ROOT\batfile\shell\open\command\(default)en "%windir%\system32\cmd.exe" /k "%windir%\system32\cmd" /c "%1" %*.

Wernight
fuente
1
Pensé que eso "%*"pasa la lista completa de parámetros, entonces ¿no pasaría esto el primer parámetro dos veces, una "%1"y otra vez como el primer parámetro de "%*"?
Kevin Fegan
1
@KevinFegan No he comprobado el motivo, pero% 1 debería mantener las comillas, lo que significa que posiblemente se doblemente en algunos casos. También hay una diferencia entre %1 %2 %3 ..y %*que no recuerdo en este momento, pero %1 %2 %3funciona en algunos casos donde %*falla.
Wernight
3

Acabo de encontrar una solución tonta después de leer grawityla respuesta.

Mi caso de uso fue configurar un entorno de consola en el trabajo donde se bloquean todas las soluciones más razonables. Todo lo que necesito es establecer PATH y configurar algunos alias de doskey y ser arrojado al shell.

Mi solución (acaba de probar en Win7) como agregar cmdcomo la última línea en el archivo por lotes. Esto ejecuta un símbolo del sistema anidado que hereda el entorno de su padre. Ese shell secundario mantiene abierto el proceso por lotes hasta que SALIR, momento en el cual el lote no tiene procesos secundarios y también sale.

kitsu.eb
fuente
2

En lugar de usar PAUSE (prefiero CHOICE o TIMEOUT que usar PAUSE cuando sea necesario), puede usar la solución aquí: 886848 / how-to-make-windows-batch-file-pause-when-doble-click .

De esta manera, si hace clic en un archivo por lotes o enlace (acceso directo) desde el Explorador de Windows, puede hacer que el programa de archivos por lotes se pause antes de salir para poder ver la salida del programa y cualquier mensaje de error.

Con CHOICE, puede programar la capacidad para que el usuario seleccione una variedad de acciones, y el uso de TIMEOUT puede permitir que la ventana se cierre después de un retraso de tiempo (desatendido). Si ejecuta el archivo por lotes desde una ventana de símbolo del sistema, estas pausas pueden ser molestas.

La solución vinculada le permitirá decidir si desea omitir las pausas si el archivo por lotes se ejecutó desde una ventana del símbolo del sistema.

Puede leer más en el enlace proporcionado, pero lo básico es que usa la variable de entorno:

%cmdcmdline%

para determinar si el archivo por lotes se ejecutó desde una ventana de comandos o no.

Entonces, lo usas así:

En el punto donde saldrá el archivo por lotes, agregue un código como este:

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
fuente
1

La mejor manera que he encontrado para evitar esto es llamar a sus archivos por lotes desde otro archivo por lotes usando inicio.

así que si normalmente ejecuta un archivo llamado go.bat, entonces crearía un segundo archivo por lotes llamado algo así como go2.bat

el contenido de go2.bat solo sería

start go.bat

la primera ventana se cierra inmediatamente, pero la que ejecuta go.bat permanece abierta

agradl
fuente
Esto funciona, acabo de poner el nombre del símbolo del sistema ejecutable en un archivo bat (1.bat) que se llama usando el comando de inicio de un segundo archivo bat "start 1.bat". La ventana de comandos permanece abierta.
eyectamenta
1

Esto funciona para la versión 5.00 del Editor del Registro de Windows.

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

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

¡Guarde los cmds anteriores en un archivo llamado algo así cmdbatfile-open.regy ejecútelo!

VumC
fuente
2
¡Bienvenido a Stack Exchange! He arreglado el formato en tu respuesta por ti. Consulte aquí para obtener ayuda sobre el formato. Además, cuando publique el código, recuerde explicar exactamente qué hace. Es posible que también desee leer el tutorial sobre cómo responder .
Blacklight Shining
1

Supongamos que tiene dos archivos por lotes que desea iniciar en su propia instancia y mantenerlos abiertos si su ejecutable sale. Llamemos a esos dos lotes A.baty B.bat.

Ahora, para simplificar, podría tener un archivo por lotes para iniciar ambos, llamemos a eso launch_both.batcon contenido:

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

Es posible que no funcione como se espera si llama exita uno de los dos archivos por lotes. Eso tendrá que ser probado.

Francois
fuente
0

Para los usuarios que usan Windows 10, tenga en cuenta que ninguna de las respuestas anteriores funciona actualmente para Windows 10.

Para Windows 10, si tiene acceso al script, debe agregar el siguiente código al final:

read

Ese código esperará una entrada antes de cerrar.

Jaycode
fuente
Recuerde que la pregunta se hizo antes de Windows 10 (hace 5 años), edite su respuesta con más información
yass
0

En respuesta a PSIXO degradado - "Esta respuesta ya estaba cubierta en la pregunta. - Ro Yo Mi Ene 20 '16 a las 5:06" - NO, NO. Las respuestas anteriores fueron: "pausa", que NO funcionó. La respuesta de PSIXO fue: "& pausa", que funciona. Analice con más cuidado antes de degradar. Ejecuté esto desde un indicador IDLE, y funcionó:

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

Por otra parte:

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

NO funcionó (el indicador de cmd parpadeó y, de hecho, devolvió un error (1)). Gracias a PSIXO por la respuesta que necesitaba. Enrique.

Enrique
fuente