Saturday 5 May 2018

Espera waitforexit processstartinfo trava


Transferências de arquivos SFTP em.


As técnicas demonstradas por este artigo são implementadas para você no assembly do WinSCP. Usar a montagem é uma abordagem recomendada sobre a implementação dessas técnicas por conta própria.


Este guia descreve como implementar a transferência de SFTP no aplicativo usando o WinSCP.


WinSCP é um cliente SFTP com interface de script que você pode usar para automatizar muitas operações que ele suporta, incluindo transferências de arquivos, sincronização e outras. Portanto, o WinSCP em si não é uma biblioteca (por exemplo, assembly) que você pode chamar diretamente. Embora este guia mostre como usá-lo sem problemas a partir do código.


Antes de começar.


Antes de começar você deve:


Usando WinSCP do código.


Executando o processo WinSCP.


Para executar o winscp use System. Diagnostics. Process. Esta classe permite executar qualquer executável, possivelmente redirecionando sua entrada e saída padrão para um fluxo acessível a partir do código. Código abaixo espera que winscp (ProcessStartInfo. FileName) pode ser encontrado no diretório de trabalho atual ou no caminho de pesquisa. Você precisa fornecer o caminho completo caso contrário.


Alimentando comandos de script usando entrada padrão.


Você pode usar o redirecionamento de entrada padrão (ProcessStartInfo. RedirectStandardInput) para alimentar comandos de script, dispensando a necessidade de montar o arquivo de script temporário.1.


Para alimentar comandos para entrada padrão, use o fluxo Process. StandardInput:


Capturando saídas do processo WinSCP.


Embora você possa redirecionar a saída padrão do processo WinSCP, na verdade não é muito útil, já que a saída do WinSCP não possui nenhum formulário predefinido (não pode ser analisado). Embora possa ser útil capturá-lo, caso deseje mostrá-lo a um usuário em sua GUI ou para fins de diagnóstico.


Se você quiser coletar a saída, redirecione a saída padrão antes de iniciar o WinSCP (ProcessStartInfo. RedirectStandardOutput) e leia o fluxo de saída (Process. StandardOutput). Você precisa coletar continuamente a saída enquanto o script está sendo executado. O fluxo de saída tem capacidade limitada. Depois de preenchido, o WinSCP trava à espera de espaço livre, nunca terminando. Isso significa que você não pode usar Process. WaitForExit por conta própria para aguardar a conclusão do script. Alternativa conveniente é StreamReader. ReadToEnd:


Usando o arquivo de log.


Para capturar os resultados do script, você pode usar o log XML. Para isso, você precisa instruir o WinSCP a armazenar o arquivo de log usando o parâmetro de linha de comando / xmllog (ProcessStartInfo. Arguments).


Se você precisar ler o arquivo de log continuamente, precisará usar o analisador baseado em fluxo (como XmlReader). Consultar exemplo.


O exemplo a seguir mostra como usar a análise baseada em árvore usando o XPathDocument:


Em caso de erro, você pode verificar se há elementos de mensagem para capturar qualquer mensagem de erro associada:


Em caso de sucesso, você pode, por exemplo extrair listagem de diretórios gerada pelo comando ls dentro do elemento ls:


Aguardando o script ser concluído.


Use Process. WaitForExit para aguardar o processo WinSCP concluir.


Se você tiver redirecionado o fluxo de saída, primeiro precisará ler o fluxo de saída até o final.


Uma boa prática é fechar o fluxo de entrada também, se você tiver redirecionado.


Verificando o código de saída.


Quando o script WinSCP for concluído, verifique o código de saída (Process. ExitCode) do processo:


Exemplo C # completo.


Partes individuais deste exemplo são explicadas no capítulo anterior.


Exemplo completo de VB.


Partes individuais deste exemplo são explicadas no primeiro capítulo. Observe que o exemplo VB não foi testado. É baseado no exemplo C # acima, que foi. Sinta-se à vontade para consertá-lo.


Exemplo de uso.


Eu resolvi assim:


Eu redirecionei tanto a entrada, saída e erro e lidou com a leitura de fluxos de saída e erro. Essa solução funciona para o SDK 7- 8,1, tanto para o Windows 7 quanto para o Windows 8.


Eu tentei fazer uma classe que resolveria seu problema usando leitura de fluxo assíncrona, levando em consideração Mark Byers, Rob, stevejay respostas. Ao fazer isso, percebi que há um erro relacionado à leitura do fluxo de saída do processo assíncrono.


Você não pode fazer isso:


Você receberá System. InvalidOperationException: StandardOut não foi redirecionado ou o processo ainda não foi iniciado.


Então você precisa iniciar a leitura assíncrona 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 defini-los como assíncronos:


Então, algumas pessoas podem dizer que você só precisa ler o fluxo antes de defini-lo como assíncrono. Mas o mesmo problema ocorre. Haverá uma condição de corrida entre a leitura síncrona e o fluxo em modo assíncrono.


Não há como obter uma leitura assíncrona segura de um fluxo de saída de um processo na maneira real como "Process" e "ProcessStartInfo" foram projetados.


Provavelmente, é melhor usar a leitura assíncrona, como sugerido por outros usuários para o seu caso. Mas você deve estar ciente de que pode perder alguma informação 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 descartada (tentei as "soluções" das outras respostas).


Então decidi sugerir outra solução:


Este código depurado e funciona perfeitamente.


Introdução.


A resposta aceita atualmente não funciona (gera exceção) e há muitas soluções alternativas, mas nenhum código completo. Isto é, 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 o código completo com base em como eu quero usar o método Process. Start.


Eu usei-o para criar um diálogo de progresso em torno dos comandos do git. É assim que eu usei:


Em teoria, você também pode combinar stdout e stderr, mas eu não testei isso.


As outras soluções (incluindo EM0s) ainda estão em deadlock para meu aplicativo, devido a tempos limite internos e ao uso de StandardOutput e StandardError pelo aplicativo gerado. Aqui está o que funcionou para mim:


Editar: adicionada inicialização do StartInfo ao exemplo de código.


Este post talvez desatualizado, mas eu descobri a causa principal porque normalmente travar é devido ao estouro de pilha para a saída redirectStandard ou se você tiver redirectStandarderror.


Como os dados de saída ou os dados de erro são grandes, isso causará um tempo de interrupção, pois ainda está sendo processado por duração indefinida.


então, para resolver esse problema:


Eu acho que essa é uma abordagem simples e melhor (não precisamos do AutoResetEvent):


Eu estava tendo o mesmo problema, mas o motivo era diferente. No entanto, isso aconteceria no Windows 8, mas não no Windows 7. A linha a seguir parece ter causado o problema.


A solução foi NÃO desabilitar o UseShellExecute. Eu agora recebi uma janela popup do Shell, que é indesejada, mas muito melhor do que o programa esperando que nada de especial aconteça. Então eu adicionei a seguinte solução para isso:


Agora, a única coisa que me incomoda é por que isso está acontecendo no Windows 8 em primeiro lugar.


Eu sei que esta é a ceia de idade, mas, depois de ler esta página inteira, nenhuma das soluções estava funcionando para mim, embora eu não tenha tentado Muhammad Rehan como o código foi 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, eu acho que é algo a ver com o comprimento da saída antes de uma marca EOF.


De qualquer forma, a solução que funcionou para mim foi 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!


Depois de ler todos os posts aqui, resolvi a solução consolidada de Marko Avlijaš. No entanto, isso não resolveu todos os meus problemas.


Em nosso ambiente, temos um serviço do Windows que está programado para executar centenas de arquivos. bat. cmd. exe diferentes. etc arquivos que se acumularam ao longo dos anos e foram escritos por muitas pessoas diferentes e em diferentes estilos. Nós não temos controle sobre a escrita dos programas & amp; scripts, somos responsáveis ​​apenas pelo agendamento, execução e geração de relatórios sobre sucesso / falha.


Então eu tentei praticamente todas as sugestões aqui com diferentes níveis de sucesso. A resposta de Marko foi quase perfeita, mas quando executada como um serviço, nem sempre captava stdout. Eu nunca cheguei ao fundo do por que não.

No comments:

Post a Comment