пятница, 15 июня 2018 г.

Redirect standardoutput waitforforexit


Redirectstandardoutput waitforexit
Eu tenho um aplicativo que chama outro processo em uma janela de comando e esse processo tem estatísticas de atualização que a saída para a janela do console. Eu pensei que esta era uma operação bastante simples, mas não consigo fazê-lo funcionar. Estou esquecendo de algo?
Idealmente, o que eu gostaria é que, à medida que a saída mude dentro desse processo, eu acerte ou os dados entrem no leitor, de modo a obter eventos.
Qualquer ajuda seria ótima, eu sinto que esta é uma pergunta de novato, mas parece estar faltando alguma coisa.
Eu já experimentei isso antes. Às vezes, a maneira pela qual o processo que você está chamando para o console não é compatível com esse tipo de redirecionamento de saída. Eu tive a sorte de, neste caso, poder modificar o processo externo para contornar isso.
Você pode tentar executar seu código em outro processo que é enviado para o console e ver se ele funciona corretamente. Ele lê sobre direito para mim agora.
Eu fui e puxei um bloco de código que eu usei para fazer isso. Isso está em um aplicativo WPF que redireciona a saída do processo para a janela. Observe a ligação do evento. Como esse é o WPF, tenho que invocar minha chamada para gravar os dados. Como você não está preocupado com o bloqueio, você deve poder simplesmente substituí-lo por:

Redirectstandardoutput waitforexit
Eu inicio um processo para executar o PsExec assim:
PsExec é executado normalmente, mas process. WaitForexit (120000) não sai antes do tempo limite e a saída padrão tem apenas as 3 primeiras linhas de saída do PsExec.
Se eu definir redirectStandardOutput como false, não há problema.
Você poderia me ajudar?
Todas as respostas.
Com base em meu entendimento, o método Process. WaitForExit (int32) não significa sair quando o tempo limite acabar.
A sobrecarga WaitForExit (Int32) é usada para fazer o segmento atual aguardar até que o processo associado seja finalizado. Essa sobrecarga instrui o componente Process a aguardar uma quantidade finita de tempo para o processo sair. Se o processo associado não sair no final do intervalo porque a solicitação para finalizar é negada, false é retornado para o procedimento de chamada. Você pode especificar um número negativo (Infinito) por milissegundos e Processo. WaitForExit (Int32) irá se comportar da mesma forma que a sobrecarga WaitForExit.
Se você quiser fechar o processo, você pode usar o seguinte código para fazer o que quiser:
Por favor, lembre-se de marcar as respostas como respostas se elas ajudarem e desmarcá-las, se elas não ajudarem.

System. Diagnostics. Process, Suspensão do processo RedirectStandardOutput.
Em um dos desenvolvimentos de nosso aplicativo interno da Web, estávamos executando um aplicativo de console com determinados argumentos de forma síncrona e tentando exibir os resultados no front-end.
Quando ativamos o processo, posso ver o processo sendo iniciado no gerenciador de tarefas e ele nunca sai, após um período de tempo (configuração de tempo limite do IIS), o tempo limite do aplicativo da Web é encerrado.
No final, descobrimos que o motivo é devido a uma condição de bloqueio inativo 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 responsável pela chamada do fluxo StandardOutput e a gravação do processo filho nesse fluxo. Essas dependências podem resultar em condições de deadlock. Quando o chamador lê o fluxo redirecionado de um processo filho, ele depende do filho. O chamador aguarda na operação de leitura até que o filho grave no fluxo ou feche o fluxo. Quando o processo filho grava dados suficientes para preencher seu fluxo redirecionado, ele depende do pai. O processo filho aguarda na próxima operação de gravação até que o pai leia o fluxo completo ou feche o fluxo. A condição de deadlock resulta quando o chamador e o processo filho aguardam um ao outro para concluir uma operação e nenhum deles pode prosseguir.
A solução é realmente simples, veja o snippet de código abaixo.
// Iniciar o processo filho.
Processo p = new Process ();
// Redirecionar o fluxo de saída do processo filho.
// Não espere o processo filho sair antes.
// lendo até o final de seu fluxo redirecionado.
// Leia o fluxo de saída primeiro e aguarde.
saída de string = p. StandardOutput. ReadToEnd ();
BTW, a maior parte da explicação é do MSDN, mas demorei um pouco para descobrir.
Autor: Saravana Kumar.
Saravana Kumar é o fundador e CTO do BizTalk360, um software corporativo que atua como uma solução completa para melhor administração, operação, suporte e monitoramento de ambientes do Microsoft BizTalk Server. Ver todas as mensagens de Saravana Kumar.

Propriedade Process. StandardOutput.
A documentação de referência da API. NET tem uma nova página. Visite o Navegador da API. NET em docs. microsoft para ver a nova experiência.
Obtém um fluxo usado para ler a saída textual do aplicativo.
Assembly: System (no System. dll)
Valor da propriedade.
Um StreamReader que pode ser usado para ler o fluxo de saída padrão do aplicativo.
O fluxo StandardOutput foi aberto para operações de leitura assíncrona com BeginOutputReadLine.
Quando um processo grava texto em seu fluxo padrão, esse texto é normalmente exibido no console. Ao 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 maneira diferente ou gravar a saída no console e em um arquivo de log designado.
Para usar o StandardOutput, você deve definir ProcessStartInfo. UseShellExecute como false e deve definir ProcessStartInfo. RedirectStandardOutput como true. Caso contrário, a leitura do fluxo StandardOutput gerará uma exceção.
O fluxo 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 grave em seu fluxo StandardOutput ou feche o fluxo.
Por outro lado, BeginOutputReadLine inicia operações de leitura assíncrona no fluxo StandardOutput. Esse método ativa um manipulador de eventos designado para a saída do fluxo e retorna imediatamente ao responsável pela chamada, que pode executar outro trabalho enquanto a saída do fluxo é direcionada para o manipulador de eventos.
As operações de leitura síncrona introduzem uma dependência entre a leitura do responsável pela chamada do fluxo StandardOutput e a gravação do processo filho nesse fluxo. Essas dependências podem resultar em condições de deadlock. Quando o chamador lê o fluxo redirecionado de um processo filho, ele depende do filho. O chamador aguarda na operação de leitura até que o filho grave no fluxo ou feche o fluxo. Quando o processo filho grava dados suficientes para preencher seu fluxo redirecionado, ele depende do pai. O processo filho aguarda na próxima operação de gravação até que o pai leia o fluxo completo ou feche o fluxo. A condição de deadlock resulta quando o chamador e o processo filho aguardam um ao outro para concluir uma operação e nenhum deles pode prosseguir. Você pode evitar deadlocks avaliando dependências entre o chamador e o processo filho.
O seguinte código C #, por exemplo, mostra como ler de um fluxo redirecionado e aguardar a saída do processo filho.
O exemplo de código evita uma condição de deadlock chamando p. StandardOutput. ReadToEnd antes de p. WaitForExit. Uma condição de deadlock pode resultar se o processo pai chama p. WaitForExit antes de p. StandardOutput. ReadToEnd e o processo filho grava texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente que o processo filho fosse encerrado. O processo filho esperaria indefinidamente que o pai lesse todo o fluxo StandardOutput.
Há um problema semelhante quando você lê todo o texto da saída padrão e dos fluxos de erro padrão. O seguinte código C #, por exemplo, executa uma operação de leitura nos dois fluxos.
O exemplo de código evita a condição de deadlock executando operações de leitura assíncrona no fluxo StandardOutput. Uma condição de deadlock resulta se o processo pai chamar p. StandardOutput. ReadToEnd seguido por p. StandardError. ReadToEnd e o processo filho grava texto suficiente para preencher seu fluxo de erro. O processo pai esperaria indefinidamente que o processo filho fechasse seu fluxo StandardOutput. O processo filho esperaria indefinidamente que o pai lesse o fluxo completo do StandardError.
Você pode usar operações de leitura assíncronas para evitar essas dependências e seu potencial de deadlock. Como alternativa, você pode evitar a condição de deadlock criando dois threads e lendo a saída de cada fluxo em um thread separado.
Você não pode mesclar operações de leitura assíncrona e síncrona em um fluxo redirecionado. Depois que o fluxo redirecionado de um processo é aberto no modo assíncrono ou síncrono, todas as operações de leitura adicionais nesse fluxo devem estar no mesmo modo. Por exemplo, não siga BeginOutputReadLine com uma chamada para ReadLine no fluxo StandardOutput ou vice-versa. No entanto, você pode ler dois fluxos diferentes em modos diferentes. Por exemplo, você pode chamar BeginOutputReadLine e, em seguida, chamar ReadLine para o fluxo StandardError.

VBlog do Lucian VBlog Lucian.
Às vezes, você quer iniciar um utilitário externo e enviar entrada para ele e também capturar sua saída. Mas é fácil entrar em um impasse desse jeito.
Usando p como novo System. Diagnostics. Process.
p. StandardInput. Write ("world" & amp; vbCrLf & amp; "hello")
'deadlock aqui se p precisa escrever mais de 12k para StandardOutput.
Dim op = p. StandardOutput. ReadToEnd ()
Console. WriteLine ("OUTPUT:"): Console. WriteLine (op)
O impasse neste caso surge porque "cat" (um utilitário unix padrão) primeiro lê a partir de StandardInput, em seguida, grava em StandardOutput, em seguida, lê novamente, e assim por diante, até que não haja mais nada para ler. Mas se o seu StandardOutput enche ninguém para lê-lo, então ele não pode mais escrever e bloquear.
O número "12k" é arbitrário e eu não confiaria nele.
Usando p como novo System. Diagnostics. Process.
'deadlock aqui se p precisa escrever mais de 12k para StandardError.
Dim op = p. StandardOutput. ReadToEnd ()
Dim err = p. StandardError. ReadToEnd ()
Console. WriteLine ("OUTPUT:"): Console. WriteLine (op)
Console. WriteLine ("ERROR:"): Console. WriteLine (err)
A documentação do MSDN diz, "Você pode usar operações de leitura assíncrona para evitar essas dependências e seu potencial de deadlock. Como alternativa, você pode evitar a condição de deadlock criando dois threads e lendo a saída de cada fluxo em um thread separado." 'Eu vou fazer.
Usando encadeamentos para redirecionar sem deadlock.
'BOM CÓDIGO: isso não será um impasse.
Usando p como novo diagnóstico. Processo.
'não WaitForExit ainda desde que introduziria deadlocks.
p. InputAndOutputToEnd ("world" & amp; vbCrLf & amp; "hello", op, Nothing)
Console. WriteLine ("OUTPUT:"): Console. WriteLine (op)
'' 'InputAndOutputToEnd: uma maneira prática de usar entrada / saída / erro redirecionado em uma p.
'' '& lt; nome do parametro = "p" & gt; O p para redirecionar. Tem de ter UseShellExecute definido como falso. & Lt; / param & gt;
'' '& lt; param name = "StandardInput" & gt; Esta string será enviada como entrada para a p. (deve ser Nothing, se não for StartInfo. RedirectStandardInput) & lt; / param & gt;
'' '& lt; param name = "StandardOutput" & gt; A saída de p será coletada nesta string ByRef. (deve ser Nothing se não for StartInfo. RedirectStandardOutput) & lt; / param & gt;
'' '& lt; nome do parametro = "StandardError" & gt; O erro do p será coletado nesta string ByRef. (deve ser Nothing se não for StartInfo. RedirectStandardError) & lt; / param & gt;
'' '& lt; remarks & gt; Esta função resolve o problema de deadlock mencionado em msdn. microsoft/pt-br/library/system. diagnostics. p.standardoutput. aspx</remarks>
& lt; Runtime. CompilerServices. Extension () & gt; Sub InputAndOutputToEnd (ByVal p Como Diagnostics. Process, ByVal StandardInput como String, ByRef StandardOutput como String, ByRef StandardError como String)
Se p não é nada, em seguida, lança novo ArgumentException ("p deve ser não-nulo")
'Suponha que p começou. Infelizmente não há como checar.
Se p. StartInfo. UseShellExecute Em seguida, lançar novo ArgumentException ("Set StartInfo. UseShellExecute to false")
If (p. StartInfo. RedirectStandardInput & lt; (gt; StandardInput IsNot Nothing)) Em seguida, lançar novo ArgumentException ("Fornecer uma entrada não nula somente quando StartInfo. RedirectStandardInput")
If (p. StartInfo. RedirectStandardOutput & lt; (StandardOutput IsNot Nothing)) Em seguida, lançar novo ArgumentException ("Fornecer uma saída não nula somente quando StartInfo. RedirectStandardOutput")
If (p. StartInfo. RedirectStandardError & lt; (gt; StandardError IsNot Nothing)) Em seguida, lançar novo ArgumentException ("Fornecer um erro não nulo somente quando StartInfo. RedirectStandardError")
Dim outputData As New InputAndOutputToEndData.
Dim errorData As New InputAndOutputToEndData.
Se p. StartInfo. RedirectStandardOutput Então.
outputData. Thread = Novo Threading. Thread (AddressOf InputAndOutputToEndProc)
Se p. StartInfo. RedirectStandardError Então.
errorData. Thread = Novo Threading. Thread (AddressOf InputAndOutputToEndProc)
Se p. StartInfo. RedirectStandardInput Então.
If p. StartInfo. RedirectStandardOutput Then outputData. Thread. Join (): StandardOutput = outputData. Output.
Se p. StartInfo. RedirectStandardError Então, errorData. Thread. Join (): StandardError = errorData. Output.
Se outputData. Exception IsNot Nothing Então lance outputData. Exception.
If errorData. Exception IsNot Nothing Em seguida, lance errorData. Exception.
Classe privada InputAndOutputToEndData.
Public Thread As Threading. Thread.
Fluxo público como IO. StreamReader.
Saída Pública como String.
Exceção pública como exceção.
Private Sub InputAndOutputToEndProc (ByVal data_ como objeto)
Dim dados = DirectCast (data_, InputAndOutputToEndData)
Tente: data. Output = data. Stream. ReadToEnd: captura e como exceção: data. Exception = e: End Try.
Cancelar resposta.
Por que não usar process. OutputDataReceived e process. ErrorDataReceived?
Dessa forma, você pode ecoar (ou capturar) a saída de ambos na ordem recebida.
Isso parece muito mais simples que async ou threading para mim.

Комментариев нет:

Отправить комментарий