redireccionar a saída de arquivo aguardando
Obter através da App Store Leia esta publicação em nosso aplicativo!
ProcessInfo e RedirectStandardOutput.
Eu tenho um aplicativo que chama outro processo em uma janela de comando e esse processo possui estatísticas de atualização que são enviadas para a janela do console. Eu pensei que esta era uma operação bastante simples, mas não consigo conseguir que funcione. Estou esquecendo de algo?
Idealmente, o que eu gostaria é que o resultado muda dentro desse processo que eu acertei ou os dados entram no leitor que eu obtenho eventos fora dele.
Qualquer ajuda seria excelente, eu sinto que esta é uma questão de novato, mas parece estar faltando alguma coisa.
Já experimentei isso antes. Às vezes, a forma como o processo que você está chamando de saídas para o console não é compatível com esse tipo de redirecionamento de saída. Naquele caso, tive a sorte de poder modificar o processo externo para evitar isso.
Você pode tentar executar seu código em outro processo que saia para o console e veja se ele funciona corretamente. Ele me lê direito agora.
Eu fui e puxei um bloco de código que eu costumava fazer. Isso está em um aplicativo WPF que redireciona a saída do processo para a janela. Observe a ligação do evento. Como isso é WPF, tenho que invocar minha chamada para escrever os dados. Como você não está preocupado com o bloqueio, você pode simplesmente substituir isso por:
Espero que ajude!
Não tenho certeza exatamente sobre o problema em que você está executando, mas se você estiver olhando para atuar no resultado assim que for gerado, tente se conectar ao evento OutputDataReceived do processo. Você pode especificar manipuladores para receber saída de forma assíncrona do processo. Eu usei essa abordagem com sucesso.
Consulte o evento OutputDataReceived Off Process para obter mais informações.
Usando expressões lambda, etc.:
Curiosamente, você não pode ler de saída padrão e erro padrão ao mesmo tempo:
se você redirecionar a saída padrão e o erro padrão e tente ler ambos, por exemplo, usando o seguinte código C #.
string output = p. StandardOutput. ReadToEnd ();
string error = p. StandardError. ReadToEnd ();
Nesse caso, se o processo filho escrever qualquer texto para erro padrão, ele bloqueará o processo, porque o processo pai não pode ler de erro padrão até que ele tenha terminado a leitura da saída padrão. No entanto, o processo pai não será lido a partir da saída padrão até o processo terminar. Uma solução recomendada para esta situação é criar dois tópicos para que seu aplicativo possa ler a saída de cada fluxo em um segmento separado.
O código de fluxo funcionou no VS2018.
Verifique se a saída que você espera não está sendo enviada para a saída StandardError em vez da saída StandardOutput.
System. Diagnostics. Process, RedirectStandardOutput process hanging.
Em um desenvolvimento do nosso aplicativo web interno, estávamos executando de forma síncrona aplicativos de console com certos argumentos e tentando exibir os resultados no front-end.
Quando ativamos o processo, eu consigo ver o processo ser iniciado no gerenciador de tarefas e nunca sai, após um período de tempo (configuração de tempo limite do IIS), o aplicativo da Web expira.
No final, descobrimos que o motivo é devido a uma condição de bloqueio morto entre o processo pai (w3wp) e o processo filho (aplicativo de console).
As operações de leitura síncrona introduzem uma dependência entre a leitura do chamador do fluxo StandardOutput e a escrita do processo filho para esse fluxo. Essas dependências podem resultar em condições de impasse. Quando o chamador lê do fluxo redirecionado de um processo filho, depende da criança. O chamador aguarda a operação de leitura até que a criança grava a transmissão ou encerre o fluxo. Quando o processo filho grava dados suficientes para preencher o fluxo redirecionado, ele depende do pai. O processo filho aguarda a próxima operação de gravação até que o pai lê do fluxo completo ou fecha o fluxo. A condição de deadlock resulta quando o processo do chamador e filho aguardam um para o outro para concluir uma operação, e nenhum deles pode prosseguir.
A solução é realmente simples, veja o snippet de código abaixo.
// Inicie o processo filho.
Processo p = novo Processo ();
// Redirecione o fluxo de saída do processo filho.
// Não espere que o processo filho saia antes.
// leitura até o final do seu fluxo redirecionado.
// Leia o fluxo de saída primeiro e depois aguarde.
string output = p. StandardOutput. ReadToEnd ();
BTW, a maioria das explicações é do MSDN, mas demorou um pouco para descobrir.
Autor: Saravana Kumar.
Saravana Kumar é o Fundador e CTO do BizTalk360, um software corporativo que atua como uma solução tudo-em-um para melhor administração, operação, suporte e monitoramento de ambientes do Microsoft BizTalk Server.
redireccionar a saída de arquivo aguardando
Eu uso System. Diagnostics. Process. Start () para executar o arquivo e use. WaitForExit () para aguardar a conclusão do processo.
Eu então uso File. Delete (filename) para excluir o arquivo executável.
Isso me leva a acreditar que, de alguma forma, o processo ainda está vivo e bloqueando o arquivo executável mesmo depois que a chamada. WaitForExit () retorna.
Qualquer idéia de por que isso acontece, e se houver alguma correção para isso (além de colocar dorme no código)?
Marcado como resposta por Samuel Stanojevic sexta-feira, 08 de janeiro de 2018 4:20 PM Editado por Tergiver sexta-feira, 08 de janeiro de 2018 4:20 PM mudou para bool, fixação de loop infinito.
A Microsoft está conduzindo uma pesquisa on-line para entender sua opinião sobre o site da Msdn. Se você optar por participar, a pesquisa on-line será apresentada quando você deixar o site Msdn.
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.
Propriedade ProcessStartInfo. RedirectStandardOutput.
A documentação de referência da API tem uma nova casa. Visite o navegador da API no docs. microsoft para ver a nova experiência.
Obtém ou define um valor que indica se a saída textual de um aplicativo está gravada no fluxo Process. StandardOutput.
Assembly: System (no System. dll)
Valor da propriedade.
Quando um Processo grava texto em seu fluxo padrão, esse texto normalmente é exibido no console. Ao configurar o RedirectStandardOutput para true para redirecionar o fluxo StandardOutput, você pode manipular ou suprimir a saída de um processo. Por exemplo, você pode filtrar o texto, formatá-lo de forma diferente ou escrever a saída para o console e um arquivo de log designado.
Você deve definir UseShellExecute como falso se desejar configurar o RedirectStandardOutput como verdadeiro. Caso contrário, a leitura do fluxo StandardOutput lança uma exceção.
O fluxo de saída StandardOutput redirecionado pode ser lido de forma síncrona ou assíncrona. Métodos como Read, ReadLine e ReadToEnd executam operações de leitura síncrona no fluxo de saída do processo. Essas operações de leitura síncrona não são concluídas até que o Processo associado escreva seu fluxo StandardOutput ou encerre o fluxo.
Em contraste, BeginOutputReadLine inicia operações de leitura assíncronas no fluxo StandardOutput. Este método habilita um manipulador de eventos designado (veja OutputDataReceived) para a saída do fluxo e retorna imediatamente ao chamador, o que pode executar outro trabalho enquanto a saída do fluxo é direcionada para o manipulador de eventos.
O aplicativo que está processando a saída assíncrona deve chamar o método WaitForExit para garantir que o buffer de saída tenha sido liberado.
As operações de leitura síncrona introduzem uma dependência entre a leitura do chamador do fluxo StandardOutput e a escrita do processo filho para esse fluxo. Essas dependências podem causar condições de bloqueio. Quando o chamador lê do fluxo redirecionado de um processo filho, depende da criança. O chamador aguarda a operação de leitura até que a criança escreva no fluxo ou encerre o fluxo. Quando o processo filho grava dados suficientes para preencher o fluxo redirecionado, ele depende do pai. O processo filho aguarda a próxima operação de gravação até que o pai lê do fluxo completo ou fecha o fluxo. A condição de impasse ocorre quando o processo do chamador e filho aguardam um ao outro para completar uma operação, e nenhuma delas pode continuar. Você pode evitar deadlocks avaliando as dependências entre o chamador eo processo filho.
Por exemplo, o seguinte código C # mostra como ler de um fluxo redirecionado e aguarde até que o processo filho saia.
O exemplo de código evita uma condição de bloqueio chamando p. StandardOutput. ReadToEnd antes de p. WaitForExit. Uma condição de impasse pode resultar se o processo pai chama p. WaitForExit antes de p. StandardOutput. ReadToEnd eo processo filho grava texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente o processo filho para sair. O processo filho esperaria indefinidamente para o pai ler do fluxo de StandardOutput completo.
Há um problema semelhante ao ler todo o texto da saída padrão e dos fluxos de erro padrão. Por exemplo, o seguinte código C # executa uma operação de leitura em ambos os fluxos.
O exemplo de código evita a condição de bloqueio executando operações de leitura assíncronas no fluxo StandardOutput. Um estado de impasse resulta se o processo pai chamar p. StandardOutput. ReadToEnd seguido de p. StandardError. ReadToEnd e o processo filho escreve texto suficiente para preencher o fluxo de erros. O processo pai aguardaria indefinidamente o processo filho para fechar o fluxo StandardOutput. O processo filho esperaria indefinidamente para o pai ler do fluxo completo do StandardError.
Você pode usar operações de leitura assíncronas para evitar essas dependências e seu potencial de impasse. Alternativamente, você pode evitar a condição de bloqueio criando dois tópicos e lendo a saída de cada fluxo em um segmento separado.
Eu uso System. Diagnostics. Process. Start () para executar o arquivo e use. WaitForExit () para aguardar a conclusão do processo.
Eu então uso File. Delete (filename) para excluir o arquivo executável.
Isso me leva a acreditar que, de alguma forma, o processo ainda está vivo e bloqueando o arquivo executável mesmo depois que a chamada. WaitForExit () retorna.
Qualquer idéia de por que isso acontece, e se houver alguma correção para isso (além de colocar dorme no código)?
Marcado como resposta por Samuel Stanojevic sexta-feira, 08 de janeiro de 2018 4:20 PM Editado por Tergiver sexta-feira, 08 de janeiro de 2018 4:20 PM mudou para bool, fixação de loop infinito.
A Microsoft está conduzindo uma pesquisa on-line para entender sua opinião sobre o site da Msdn. Se você optar por participar, a pesquisa on-line será apresentada quando você deixar o site Msdn.
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.
Propriedade ProcessStartInfo. RedirectStandardOutput.
A documentação de referência da API tem uma nova casa. Visite o navegador da API no docs. microsoft para ver a nova experiência.
Obtém ou define um valor que indica se a saída textual de um aplicativo está gravada no fluxo Process. StandardOutput.
Assembly: System (no System. dll)
Valor da propriedade.
Quando um Processo grava texto em seu fluxo padrão, esse texto normalmente é exibido no console. Ao configurar o RedirectStandardOutput para true para redirecionar o fluxo StandardOutput, você pode manipular ou suprimir a saída de um processo. Por exemplo, você pode filtrar o texto, formatá-lo de forma diferente ou escrever a saída para o console e um arquivo de log designado.
Você deve definir UseShellExecute como falso se desejar configurar o RedirectStandardOutput como verdadeiro. Caso contrário, a leitura do fluxo StandardOutput lança uma exceção.
O fluxo de saída StandardOutput redirecionado pode ser lido de forma síncrona ou assíncrona. Métodos como Read, ReadLine e ReadToEnd executam operações de leitura síncrona no fluxo de saída do processo. Essas operações de leitura síncrona não são concluídas até que o Processo associado escreva seu fluxo StandardOutput ou encerre o fluxo.
Em contraste, BeginOutputReadLine inicia operações de leitura assíncronas no fluxo StandardOutput. Este método habilita um manipulador de eventos designado (veja OutputDataReceived) para a saída do fluxo e retorna imediatamente ao chamador, o que pode executar outro trabalho enquanto a saída do fluxo é direcionada para o manipulador de eventos.
O aplicativo que está processando a saída assíncrona deve chamar o método WaitForExit para garantir que o buffer de saída tenha sido liberado.
As operações de leitura síncrona introduzem uma dependência entre a leitura do chamador do fluxo StandardOutput e a escrita do processo filho para esse fluxo. Essas dependências podem causar condições de bloqueio. Quando o chamador lê do fluxo redirecionado de um processo filho, depende da criança. O chamador aguarda a operação de leitura até que a criança escreva no fluxo ou encerre o fluxo. Quando o processo filho grava dados suficientes para preencher o fluxo redirecionado, ele depende do pai. O processo filho aguarda a próxima operação de gravação até que o pai lê do fluxo completo ou fecha o fluxo. A condição de impasse ocorre quando o processo do chamador e filho aguardam um ao outro para completar uma operação, e nenhuma delas pode continuar. Você pode evitar deadlocks avaliando as dependências entre o chamador eo processo filho.
Por exemplo, o seguinte código C # mostra como ler de um fluxo redirecionado e aguarde até que o processo filho saia.
O exemplo de código evita uma condição de bloqueio chamando p. StandardOutput. ReadToEnd antes de p. WaitForExit. Uma condição de impasse pode resultar se o processo pai chama p. WaitForExit antes de p. StandardOutput. ReadToEnd eo processo filho grava texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente o processo filho para sair. O processo filho esperaria indefinidamente para o pai ler do fluxo de StandardOutput completo.
Há um problema semelhante ao ler todo o texto da saída padrão e dos fluxos de erro padrão. Por exemplo, o seguinte código C # executa uma operação de leitura em ambos os fluxos.
O exemplo de código evita a condição de bloqueio executando operações de leitura assíncronas no fluxo StandardOutput. Um estado de impasse resulta se o processo pai chamar p. StandardOutput. ReadToEnd seguido de p. StandardError. ReadToEnd e o processo filho escreve texto suficiente para preencher o fluxo de erros. O processo pai aguardaria indefinidamente o processo filho para fechar o fluxo StandardOutput. O processo filho esperaria indefinidamente para o pai ler do fluxo completo do StandardError.
Você pode usar operações de leitura assíncronas para evitar essas dependências e seu potencial de impasse. Alternativamente, você pode evitar a condição de bloqueio criando dois tópicos e lendo a saída de cada fluxo em um segmento separado.
No comments:
Post a Comment