Como impedir que o prompt de comando seja fechado após a execução?

54

Meu problema é que, no Windows, há janelas da linha de comando que fecham imediatamente após a execução. Para resolver isso, quero que o comportamento padrão seja que a janela seja mantida aberta. Normalmente, esse comportamento pode ser evitado com três métodos que me vêm à mente:

  1. Colocar uma pauselinha após programas em lote para solicitar ao usuário que pressione uma tecla antes de sair
  2. Executando esses arquivos em lotes ou outras ferramentas de manipulação de linha de comando (até mesmo a inicialização, a reinicialização do serviço etc. com net start xyou algo semelhante) em cmd.exe(Iniciar - Executar - cmd.exe)
  3. Executando estes programas com o cmd /kseguinte: cmd /k myprogram.bat

Mas existem outros casos em que o usuário:

  1. Executa o programa pela primeira vez e não sabe que o programa fornecido será executado no Prompt de Comando (Windows Command Processor), por exemplo, ao executar um atalho no menu Iniciar (ou em outro lugar), OU
  2. Acha um pouco desconfortável executar o cmd.exe o tempo todo e não tem tempo / oportunidade para reescrever o código desses comandos em todos os lugares para colocar uma pausa após eles ou evitar sair explicitamente.

Eu li um artigo sobre como alterar o comportamento padrão cmd.exeao abri-lo explicitamente, criando uma entrada de AutoRun e manipulando seu conteúdo nesses locais:

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

(Os itens de AutoRun são _String values_...)

Eu coloquei cmd /d /kcomo um valor para tentar, mas isso não mudou o comportamento dos itens mencionados acima ... Ele apenas mudou o comportamento da janela da linha de comando ao abri-la explicitamente (Start-Run- cmd.exe).

Então, como isso funciona? Você pode me dar alguma idéia para resolver este problema?

Sk8erPeter
fonte
10
Sua pergunta com todas as explicações fez minha cabeça querer explodir. Você pode dizer algo como: Quero executar um arquivo em lotes com este comando "exemplo" e quero que a caixa de comando permaneça aberta quando terminar. É isso que você está perguntando? Por favor, coloque um exemplo próximo do código.
KCotreau
11
+1 Concordado. Um pouco detalhado, reconsidere sua pergunta e, se possível, use um exemplo e componha uma pergunta mais sucinta.
slotishtype 04/07
2
Esse é um comportamento normal e, embora sua pergunta certamente seja válida, você deve estar se perguntando por que precisa manter o prompt de comando aberto depois (a maioria dos utilitários é criada com essa ressalva).
Breakout
11
Na minha opinião, essa não é uma pergunta real. Como você acabou de instruir o usuário a usar um arquivo em lotes. Se essa não é a intenção da pergunta, esclareça sua pergunta removendo qualquer informação confusa e explique qual é seu objetivo real. É difícil chegar com a resposta certa se é claro ...
Tamara Wijsman
11
@ Randolf Richardson, é porque essas ferramentas não devem ser vistas por um usuário final (afinal, é por isso que usamos GUIs agora). Se você precisou dessas informações, a maioria dos grupos de TI enviará arquivos em lote para coletar as informações apropriadas do sistema e exibi-las. Não vejo nenhuma maneira possível de que, se uma solução para essa pergunta for encontrada, ela causará menos problemas do que a solução - tantas coisas são enviadas stdoutconstantemente, que nunca foram visíveis por um bom motivo.
Breakthrough

Respostas:

27

Eu tenho uma solução que só pode ser aplicada em .cmde .batarquivos:

Abra regedite vá para cada um dos seguintes:

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

Agora altere o "Valor da chave padrão" para cmd.exe /k "%1" %*. Agora, toda janela de script em lote permanecerá aberta após sua execução.

Observe que isso é como usar cmd.exe /c cmd.exe /k program.bat, o que significa que outra instância do CMD será iniciada na pai. Não consegui encontrar como substituir o primeiro /cargumento.

Você também pode fazer isso com [exefile], mas agora ele mostrará uma caixa de console vazia se o executável tiver uma GUI.

not2qubit
fonte
4
+1 por ter a única solução aqui que realmente responde à pergunta dada. Infelizmente, acho que isso pode ser um vazamento de memória esperando para acontecer. O que acontece quando um serviço lança um novo arquivo em lotes sem especificar o CMD.EXE na linha CMD? Esse código não será usado nesse caso? Isso não criará uma nova janela em uma área de trabalho não interativa e deixará aberta até que você reinicie?
krowe2
@APerson Sua edição quebrou o comando ao não incluir o *. Por favor, tenha mais cuidado ao editar!
Not2qubit
@ not2qubit Desculpe, não percebi que apaguei três asteriscos em vez de dois. Vai fazer.
aperson
17

Quote Microsoft :

Um console é fechado quando o último processo anexado a ele termina ou chama o FreeConsole.

Em outras palavras, a janela do console do Win32 sempre será fechada quando o último programa em execução dentro dela sair e você não poderá alterar isso.


(Para programas de MS-DOS de 16 bits, o Windows oferece a opção "Fechar na saída" na caixa de diálogo de propriedades, mas isso não é uma exceção ao comportamento acima: é o processo NTVDM que mantém a janela aberta. Além disso, essa opção é novamente por programa.)

gravidade
fonte
13
+1 para entender como e por que as janelas do console fecham (ao contrário da maioria dos que apenas dizem "OMG, POR QUE NÃO PODE FICAR ABERTO !!!!!!!!!!! 1111one"). Está se comportando como planejado, e deve permanecer assim IMHO. Essa é a principal razão pela qual temos fluxos e arquivos em lote padrão em primeiro lugar.
Breakout
27
@ Breakthrough A questão é How can I do X, não In your opinion, should I do X. Essa resposta é inútil, implica que X é impossível, quando soluções parciais já foram apresentadas em outro lugar. (-1)
Soberbo
7

Basta abrir um prompt de comando no local do seu arquivo em lotes e digitar manualmente o nome do arquivo em lotes para executá-lo nessa janela.

1. Navegue até a pasta em que seu executável reside
2.Shift-Clique com o botão direito do mouse e selecione "Janela de comando daqui"
3. digite o nome do executável e pressione enter
4. O processo deve ser executado, mas a janela deve permanecer aberta

Lee Harrison
fonte
11
Eu não sabia sobre Shift + clique direito. Além disso, você pode arrastar e soltar o exe em uma janela do cmd, que automaticamente coloca o caminho para você.
Superbest
11
Isso geralmente funciona para mim, mas aparentemente não é uma coisa certa, porque estou aqui procurando uma solução precisamente porque não está funcionando na minha situação atual.
RenniePet
esta é a solução mais fácil e deve ser marcado como a resposta correta
Vicky Kapadia
4

cmd.exe /klhe dará problemas com algum lote. Se o lote exit 1(sem /B) seu console será fechado. Um truque é usar:

cmd.exe /k cmd /c ...

Para usar isso por padrão para todos os arquivos em lotes, defina HKEY_CLASSES_ROOT\cmdfile\shell\open\command\(default)e HKEY_CLASSES_ROOT\batfile\shell\open\command\(default)como "%windir%\system32\cmd.exe" /k "%windir%\system32\cmd" /c "%1" %*.

Wernight
fonte
11
Eu pensei que "%*"passa a lista completa de parâmetros, então isso não passaria o primeiro parâmetro duas vezes, uma vez "%1"e novamente como o primeiro parâmetro de "%*"?
precisa
11
@ KevinFegan Eu não verifiquei o motivo, mas% 1 deve manter as aspas, o que significa que, em alguns casos, poderia ser citado duas vezes. Há também uma diferença entre %1 %2 %3 ..e da %*qual não me lembro agora, mas os %1 %2 %3trabalhos em alguns casos onde %*falham.
Wernight
3

Acabei de encontrar uma solução idiota depois de ler grawitya resposta.

Meu caso de uso foi configurar um ambiente de console no trabalho, onde todas as soluções mais razoáveis ​​foram bloqueadas. Tudo que eu preciso é definir PATH e configurar alguns aliases de doskey e ser despejado no shell.

Minha solução (apenas testada no Win7) como adicionar cmdcomo a última linha no arquivo em lotes. Isso executa um prompt de comando aninhado que herda o ambiente de seu pai. Esse shell filho mantém o processo em lote aberto até você SAIR, quando o lote não possui processos filhos e também sai.

kitsu.eb
fonte
2

Em vez de usar PAUSE (prefiro CHOICE ou TIMEOUT a usar PAUSE quando necessário), você pode usar a solução aqui: 886848 / como fazer-janelas-arquivo-em lote-pausar-quando-clicar duas vezes .

Dessa forma, se você clicar em um arquivo em lotes ou em um link (atalho) no Windows Explorer, poderá fazer uma pausa no programa de arquivos em lotes antes de sair para poder visualizar a saída do programa e quaisquer mensagens de erro.

Usando CHOICE, você pode programar a capacidade de o usuário selecionar uma variedade de ações a serem executadas, e usar TIMEOUT pode deixar a janela fechar após um atraso de tempo (sem supervisão). Se você executar o arquivo em lotes de dentro de uma janela do prompt de comando, essas pausas podem ser irritantes.

A solução vinculada permitirá que você decida se deseja pular as pausas se o arquivo em lotes foi executado em uma janela do prompt de comando.

Você pode ler mais no link fornecido, mas o básico é que ele usa a variável de ambiente:

%cmdcmdline%

para determinar se o arquivo em lotes foi executado em uma janela de comando ou não.

Então, você o usa assim:

No ponto em que o arquivo em lotes será encerrado, você adiciona um 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
fonte
1

A melhor maneira que encontrei para contornar isso é chamar seus arquivos em lote de outro arquivo em lote usando start.

portanto, se você normalmente executa um arquivo chamado go.bat, cria um segundo arquivo em lote chamado go2.bat

o conteúdo do go2.bat seria apenas

start go.bat

a primeira janela fecha imediatamente, mas a que está executando o seu go.bat permanece aberta

agradl
fonte
Isso funciona, basta colocar o nome do prompt de comando executável em um arquivo bat (1.bat), chamado usando o comando start de um segundo arquivo bat "start 1.bat". A janela de comando permanece aberta.
Ejectamenta # 19/17
1

Isso funciona para a versão 5.00 do Editor do Registro do Windows.

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

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

Salve os cmds acima em um arquivo chamado algo como cmdbatfile-open.rege execute-o!

VumC
fonte
2
Bem-vindo ao Stack Exchange! Corrigimos a formatação da sua resposta para você. Veja aqui a ajuda da formatação. Além disso, quando você publicar um código, lembre-se de explicar o que exatamente ele faz. Você também pode querer ler o tutorial sobre como responder .
Blacklight Shining
1

Suponha que você tenha dois arquivos em lote que deseja iniciar em sua própria instância e mantenha aberto se o executável sair. Vamos chamar esses dois lotes A.bate B.bat.

Agora, para simplificar, você pode ter um arquivo em lotes para iniciar os dois, vamos chamar assim launch_both.batcom o conteúdo:

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

Pode não funcionar como esperado se você chamar exitum dos dois arquivos em lote. Isso precisará ser testado.

François
fonte
0

Para usuários que usam o Windows 10, observe que nenhuma das respostas acima atualmente funciona para o Windows 10.

No Windows 10, se você tiver acesso ao script, precisará adicionar o seguinte código no final:

read

Esse código aguardará uma entrada antes de fechar.

jaycode
fonte
Lembre-se de que a pergunta foi feita antes do Windows 10 (há 5 anos), edite sua resposta com mais informações
yass
0

Em resposta ao PSIXO rebaixado - "Esta resposta já foi abordada na pergunta. - Ro Yo Mi 20 de janeiro de 16 às 5:06" - NÃO, NÃO foi. As respostas anteriores foram: "pausa", que NÃO funcionou. A resposta do PSIXO foi: "& pause", que funciona. Analise com mais cuidado antes de fazer o downgrade. Eu executei isso em um prompt IDLE e funcionou:

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

Por outro lado:

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

NÃO funcionou (o prompt do cmd passou e, de fato, retornou um erro (1)). Agradeço ao PSIXO pela resposta que eu precisava. Henry.

Henry
fonte