o registro de walter.
. Escrevendo enquanto aprende.
Sexta-feira, 18 de novembro de 2011.
Process. WaitForExit (Int32) bloqueia o problema.
Como você pode ver, o código inicia um processo "cmd. exe" e passa para ele o comando que eu quero ser executado.
No código eu usei o comando ping - t 8.8.8.8 que, por causa da opção - t, pings o host sem parar. O que acontece? O processo "cmd. exe" juntamente com o comando ping - t nunca sai e nunca fecha o fluxo de stdout e, portanto, o nosso código trava no Output = process. StandardOutput. ReadToEnd (); linha, porque não pode ter sucesso em ler todo o fluxo.
O mesmo acontece também se um comando em um arquivo em lotes trava por qualquer motivo e, portanto, o código acima pode funcionar continuamente por anos e, em seguida, pendure de repente sem nenhum motivo aparente.
você pode enfrentar um impasse se o comando que você atribui a "cmd. exe" ou o processo que você está chamando preenche a saída padrão ou erro padrão. Isso porque nosso código não pode alcançar as linhas.
Na verdade, o processo filho (o comando ping ou um arquivo em lote ou o processo que estiver executando) não pode continuar se o nosso programa não ler os buffers preenchidos dos fluxos e isso não pode acontecer porque o código está pendurado na linha com o processo. WaitForExit () que aguardará para sempre que o projeto filho saia.
O tamanho padrão de ambos os fluxos é de 4096 bytes. Você pode testar esses dois tamanhos com esses arquivos em lote:
Powershell waitforexit trava
Obter através da App Store Leia esta publicação em nosso aplicativo!
StandardOutput. ReadToEnd () trava [duplicado]
Esta questão já tem uma resposta aqui:
Eu tenho um programa que freqüentemente usa um programa externo e lê suas saídas. Isso funciona muito bem, usando seu processo usual de redirecionamento de saída, mas um argumento específico, por algum motivo, trava quando eu tento lê-lo, nenhuma mensagem de erro - nenhuma exceção, apenas "pára" quando ele atinge essa linha. Naturalmente, eu uso uma função centralizada para chamar e ler a saída do programa, o que é o seguinte:
A linha que trava é resultado = proc. StandardOutput. ReadToEnd (); , mas novamente, não todas as vezes, somente quando enviado um argumento específico ("start-server"). Todos os outros argumentos funcionam bem - lê o valor e o retorna. Também é estranho o jeito que ele trava. Não congela ou comete um erro ou qualquer coisa, ele simplesmente pára o processamento. Como se fosse um comando de "retorno", exceto que ele nem sequer retorna à função de chamada, ele simplesmente pára tudo com a interface ainda está funcionando. Alguém experimentou isso antes? Alguém tem alguma ideia do que eu deveria tentar? Estou assumindo que é algo inesperado dentro do fluxo em si, mas existe uma maneira de lidar / ignorar isso para que ele lê de qualquer maneira?
marcado como duplicado por Peter Duniho c # Usuários com o crachá c # podem fechar as perguntas de c # como duplicatas e reabri-las conforme necessário. 27 de junho às 2:45.
Esta pergunta foi feita antes e já tem uma resposta. Se essas respostas não respondem totalmente a sua pergunta, faça uma nova pergunta.
As soluções propostas com BeginOutputReadLine () são uma boa maneira, mas em situações como essa, não é aplicável, porque o processo (certamente com o uso de WaitForExit ()) sai antes da saída assíncrona concluída completamente.
Então, tentei implementá-lo de forma síncrona e descobriu que a solução é usar o método Peek () da classe StreamReader. Eu adicionei check for Peek () & gt; -1 com certeza que não é o fim do fluxo como no artigo MSDN descrito e, finalmente, funciona e pára de pendurar!
Aqui está o código:
O problema é que você está usando os métodos síncronos ReadToEnd nos fluxos StandardOutput e StandardError. Isso pode levar a um potencial bloqueio que você está enfrentando. Isto é mesmo descrito no MSDN. A solução está descrita lá. Basicamente, é: use a versão assíncrona BeginOutputReadLine para ler os dados do fluxo StandardOutput:
Eu tive o mesmo problema de impasse. Este trecho de código funcionou para mim.
E quanto a algo como:
Eu tive o mesmo tipo de problema que o erro estava pendurado.
Com base na sua resposta a Daniel Hilgarth, nem tentei usar esses códigos, embora eu pense que eles teriam funcionado para mim.
Uma vez que eu quero ser capaz de fazer alguma saída mais fantástica ainda, eu decidi que eu faria isso com as duas saídas sendo feitas em uma linha de fundo.
Isso funcionou para mim e me permitiu não ter que usar um tempo limite para a leitura.
Algo que é elegante e trabalhou para mim é:
Esta resposta eu encontrei aqui e o truque está usando Flush () e Close () na entrada padrão.
A solução da resposta aceita não funcionou para mim. Eu tive que usar tarefas para evitar o impasse:
Com uma função GetStreamOutput da seguinte maneira:
Apenas no caso de alguém se tropeçar com esta questão, enquanto estiver usando Windows Forms e TextBox (ou RichTextBox) para mostrar os erros e as saídas, o processo retorna em tempo real (como eles são escritos para process. StandardOutput / process. StandardError).
Você precisa usar OutputDataReceived () / ErrorDataReceived () para ler ambos os fluxos sem deadlocks, não há maneira (tanto quanto eu sei) para evitar deadlocks de outra forma, mesmo a resposta de Fedor, que agora contém a tag "Answer" e o A maioria gosta de atualizar, não faz o truque para mim.
No entanto, quando você usa o RichTextBox (ou TextBox) para enviar os dados, outro problema que você encontra é como realmente gravar os dados na caixa de texto em tempo real (uma vez que ele chega). Você recebe o acesso aos dados dentro de um dos segmentos de fundo OutputDataReceived () / ErrorDataReceived () e você só pode anexar o texto () do thread principal.
O que eu tentei pela primeira vez era chamar processo. Iniciar () de uma linha de fundo e, em seguida, chamar BeginInvoke () = & gt; AppendText () nos segmentos OutputDataReceived () / ErrorDataReceived () enquanto o thread principal era process. WaitForExit ().
No entanto, isso levou a minha forma a congelar e finalmente pendurar por toda a eternidade. Depois de alguns dias de tentativa, acabei com a solução abaixo, que parece funcionar muito bem.
Em breve, você precisa adicionar as mensagens em uma coleção concorrente dentro dos segmentos OutputDataReceived () / ErrorDataReceived () enquanto o segmento principal deve tentar constantemente extrair as mensagens dessa coleção e anexá-las na caixa de texto:
Exemplo de uso.
Resolvi assim:
Eu redirecionava a entrada, a saída e o erro e administrai a leitura dos fluxos de saída e erro. Esta solução funciona para o SDK 7- 8.1, tanto para o Windows 7 como para o Windows 8.
Eu tentei fazer uma aula que resolva seu problema usando a leitura de fluxo assíncrono, levando em conta Mark Byers, Rob, Stevejay responde. Ao fazê-lo, percebi que existe um erro relacionado à leitura assíncrona do fluxo de saída do processo.
Você não pode fazer isso:
Você receberá System. InvalidOperationException: StandardOut não foi redirecionado ou o processo ainda não começou.
Então, você deve iniciar a saída assíncrona lida após o processo ser iniciado:
Fazendo isso, faça uma condição de corrida porque o fluxo de saída pode receber dados antes de configurá-lo como assíncrono:
Então algumas pessoas podem dizer que você só precisa ler o fluxo antes de configurá-lo como assíncrono. Mas o mesmo problema ocorre. Haverá uma condição de corrida entre a leitura síncrona e configurará o fluxo em modo assíncrono.
Não há como conseguir uma leitura assíncrona segura de um fluxo de saída de um processo na forma real "Processo" e "ProcessStartInfo" foi projetado.
Você provavelmente está melhor usando a leitura assíncrona, como sugerido por outros usuários para o seu caso. Mas você deve estar ciente de que você pode perder algumas informações devido à condição de corrida.
Nenhuma das respostas acima está fazendo o trabalho.
A solução Rob trava e a solução 'Mark Byers' obtém a exceção descarta. (Eu tentei as "soluções" das outras respostas).
Então eu decidi sugerir outra solução:
Este código é depurado e funciona perfeitamente.
Eu acho que isso é uma abordagem simples e melhor (não precisamos do AutoResetEvent):
Eu estava tendo o mesmo problema, mas a razão era diferente. No entanto, isso aconteceria no Windows 8, mas não no Windows 7. A seguinte linha parece ter causado o problema.
A solução era NÃO desativar UseShellExecute. Agora recebi uma janela popup do Shell, que é indesejável, mas muito melhor do que o programa esperando que nada de particular aconteça. Então eu adicionei o seguinte trabalho para isso:
Agora, o único problema que me incomoda é o porquê isso está acontecendo no Windows 8, em primeiro lugar.
Introdução.
A resposta atualmente aceita não funciona (lança exceção) e há muitas soluções alternativas, mas nenhum código completo. Isso é, obviamente, desperdiçando muito tempo das pessoas porque esta é uma questão popular.
Combinando a resposta de Mark Byers e a resposta de Karol Tyl, escrevi um código completo baseado em como eu quero usar o método Process. Start.
Eu usei-o para criar um diálogo de progresso em torno dos comandos git. É assim que eu usei isso:
Em teoria, você também pode combinar stdout e stderr, mas não testei isso.
Eu sei que isso é velho, mas, depois de ler toda essa página, nenhuma das soluções estava funcionando para mim, embora eu não tentei Muhammad Rehan porque o código era um pouco difícil de seguir, embora eu acho que ele estava no caminho certo . Quando eu digo que não funcionou, isso não é inteiramente verdade, às vezes funcionaria bem, acho que é algo a ver com a duração da saída antes de uma marca EOF.
De qualquer forma, a solução que funcionou para mim era usar diferentes threads para ler o StandardOutput e StandardError e escrever as mensagens.
Espero que isso ajude alguém, que pensou que isso poderia ser tão difícil!
As outras soluções (incluindo o EM0) ainda estão bloqueadas para o meu aplicativo, devido a tempos de espera internos e ao uso de StandardOutput e StandardError pela aplicação gerada. Aqui está o que funcionou para mim:
Editar: inicialização adicionada de StartInfo para codificar a amostra.
Este post talvez esteja desactualizado, mas descobri a principal causa por que normalmente ele trava é devido ao excesso de pilha para o redirectStandardoutput ou se você tem redirectStandarderror.
Como os dados de saída ou os dados de erro são grandes, isso causará um tempo de espera, pois ele ainda está processando por tempo indefinido.
Existe um equivalente do shell do DOS "start / wait" & quot; no PowerShel.
Existe um equivalente do shell do DOS "start / wait" & quot; no PowerShel.
especialmente um GUI exe, para terminar antes de executar a próxima linha no.
Re: Existe um equivalente do shell DOS & quot; start / wait & quot; no PowerShel.
Brillig & quot; & lt; Brilligdiscussions. microsoft & gt; escreveu na mensagem.
& gt; Existe um equivalente do shell DOS "iniciar / aguardar", para permitir um comando,
& gt; especialmente um GUI exe, para terminar antes de executar a próxima linha no.
RE: Existe um equivalente do shell do DOS "start / wait" & quot; no PowerShel.
& gt; especialmente um GUI exe, para terminar antes de executar a próxima linha no.
A maneira mais fácil de implementar é usar uma classe,
System. Diagnostics. Process para iniciar um processo e aguarde até o processo.
& quot; System. Diagnostics. ProcessStartInfo & quot; para passar informações do processo)
$ notepad = [System. Diagnostics. Process] :: Start (& quot; notepad. exe & quot;)
Re: Existe um equivalente do shell DOS & quot; start / wait & quot; no PowerShel.
PoSH & gt; $ notepad = [System. Diagnostics. Process] :: Start (& quot; notepad. exe & quot;)
Valor: System. Boolean WaitForExit (Int32 milissegundos),
FalsePoSH & gt; $ notepad = [System. Diagnostics. Process] :: Start (& quot; notepad. exe & quot;)
Valor: System. Boolean WaitForExit (Int32 milissegundos),
& gt; & gt; & quot; Bloco de notas desistiu em 2 segundos & quot;> Else.
& gt; & gt; & quot; Notepad não desistiu em 2 segundos & quot;>
O bloco de notas não foi encerrado em 2 segundos.
PoSH & gt; se ($ notepad. WaitForExit (10000))
& gt; & gt; & quot; Notepad faleceu em 10 segundos & quot;> Else.
& gt; & gt; & quot; Notepad não desistiu em 10 segundos & quot;>
O bloco de notas parou em 10 segundos.
PoSH & gt; se ($ notepad. WaitForExit (10000))
& gt; & gt; & quot; executando por $ ((get-date) - $ notepad. StartTime) & quot;
correndo para 00: 00: 30.9150135.
& quot; Sung M Kim & quot; & lt; SungMKimdiscussions. microsoft & gt; escreveu na mensagem.
& gt; & gt; Existe um equivalente do shell DOS "start / wait", para permitir a.
& gt; & gt; especialmente um GUI exe, para terminar antes de executar a próxima linha no.
& gt; A maneira mais fácil de implementar é usar uma classe,
& gt; System. Diagnostics. Process para iniciar um processo e aguardar o processo.
& gt; O seguinte ilustra como isso pode ser feito. (Caso mais simples sem usar.
& gt; & quot; System. Diagnostics. ProcessStartInfo & quot; para passar informações do processo)
& gt; # lembre-se de que o processo do Bloco de notas aguarde.
& gt; $ notepad = [System. Diagnostics. Process] :: Start (& quot; notepad. exe & quot;)
& gt; Agora, o powershell irá pendurar após "$ notepad. WaitForExit () & quot; até você sair.
Re: Existe um equivalente do shell DOS & quot; start / wait & quot; no PowerShel.
& gt; Existe um equivalente do shell DOS "iniciar / aguardar", para permitir um comando,
& gt; especialmente um GUI exe, para terminar antes de executar a próxima linha no.
é alias para "start" quot; e "saps". Tem um parâmetro que permite que você.
especifique uma espera (indefinida ou que expira).
Re: Existe um equivalente do shell DOS & quot; start / wait & quot; no PowerShel.
& gt; Brillig & quot; & lt; Brilligdiscussions. microsoft & gt; escreveu na mensagem.
& gt; & gt; Existe um equivalente do shell DOS "start / wait", para permitir a.
& gt; & gt; especialmente um GUI exe, para terminar antes de executar a próxima linha no.
& gt; O snapin Extensões da comunidade PowerShell possui um cmdlet Start-Process que.
& gt; é alias para "start" quot; e "saps". Tem um parâmetro que permite que você.
& gt; especifique uma espera (indefinida ou que expira).
Re: Existe um equivalente do shell DOS & quot; start / wait & quot; no PowerShel.
& gt; & gt; Existe um equivalente do shell DOS "start / wait", para permitir a.
& gt; & gt; especialmente um GUI exe, para terminar antes de executar a próxima linha no.
& gt; A maneira mais fácil de implementar é usar uma classe,
& gt; System. Diagnostics. Process para iniciar um processo e aguardar o processo.
& gt; O seguinte ilustra como isso pode ser feito. (Caso mais simples sem usar.
& gt; & quot; System. Diagnostics. ProcessStartInfo & quot; para passar informações do processo)
& gt; # lembre-se de que o processo do Bloco de notas aguarde.
& gt; $ notepad = [System. Diagnostics. Process] :: Start (& quot; notepad. exe & quot;)
& gt; Agora, o powershell irá pendurar após "$ notepad. WaitForExit () & quot; até você sair.
O Vista Forums é um site independente e não foi autorizado,
patrocinado ou aprovado pela Microsoft Corporation.
"Windows Vista", o Start Orb e materiais relacionados são marcas comerciais da Microsoft Corp.
No comments:
Post a Comment