Thursday, 5 April 2018

Waitforexit não funciona


Waitforexit não funciona
Obter através da App Store Leia esta publicação em nosso aplicativo!
WaitforExit doesn & # 39; t funcionar corretamente.
Então, estou lutando por esse problema por algum tempo agora e tentei muitas maneiras diferentes de corrigi-lo, mas não posso.
Basicamente, o meu aplicativo faz é chamar um arquivo java para carregar um aplicativo em um dispositivo. Enquanto está carregando, ele está imprimindo para uma caixa de richtext, então eu gostaria de passar para o próximo arquivo. O problema que estou tendo é que, enquanto o primeiro arquivo está sendo carregado, o 2º tenta carregar quais problemas de casos. Eu tentei a espera para a saída, mas se eu fizer isso, então os dados de saída não são escritos na caixa de texto rica. Alguma ideia?
Eu tentei colocar a espera para sair em muitos lugares diferentes, mas isso não parece funcionar.
Dois métodos abaixo escrevem o stdout ou erro no campo richtext.
Qualquer ideia seria excelente. Basicamente eu preciso do processo para sair, então eu posso continuar a pensar que o forloop carrega o próximo arquivo.
Se você WaitForExit, seu aplicativo bloqueia (espera) até o processo sair. Isso significa que não é possível processar qualquer mensagem do Windows em seu segmento UI, portanto, não atualiza a UI.
Você precisa iniciar o processo "em segundo plano" para que sua UI continue atualizando. Isso pode ser feito com:
Inicie e monitore o processo de um segmento separado e passe as informações de progresso de volta para o segmento UI para exibição. Adicione um manipulador de eventos ao evento encerrado pelo processo ou examine periodicamente o sinalizador process. HasExited e use isso para saber quando o primeiro processo acabado. Seu manipulador de eventos iniciaria esse processo e, em seguida, sairá de volta para o loop de aplicativo principal, de modo que ele seja executado normalmente enquanto espera que o processo externo seja concluído.
Sente-se em um loop de espera ocupado até que ele seja concluído e processe os eventos do aplicativo. (Tenha cuidado com isso, pois quaisquer eventos que causem chamadas reentrantes para este código poderiam fazer coisas muito ruins. Geralmente, se você usar essa abordagem, você deve ter certeza de que o resto do seu aplicativo está "bloqueado" em um estado onde o conhece está ocupado aguardando a conclusão de um processo). Isso é efetivamente o que WaitForExit faz, mas também processa eventos de aplicativos, permitindo que a IU permaneça vagamente responsiva:
Talvez eu esteja totalmente errado aqui, mas.
Você precisa ter um espaço após o - jar.
Ou então, Java vai bombardear imediatamente.
Tentando mover a chamada WaitForExit para fora do segmento UI.
Como @M. Babcock mencionou, você está mantendo as atualizações na caixa de texto rica.
Uma solução semelhante a esta pode funcionar:
Modifique btnLoad_Click para iniciar um novo tópico que processa a lista (isto vai na contagem> ramo 0)

Como aguardar o Squirrel Setup. exe para sair e terminar a instalação? # 1132.
SissiKonsta comentou 18 de agosto de 2017.
Estou escrevendo um programa que exige a conclusão da instalação, copie alguns arquivos e, em seguida, inicie o aplicativo. Para fazer isso, estou usando o seguinte código:
Processo process = new Process ();
ProcessStartInfo startInfo = novo ProcessStartInfo ();
Como você pode ver, estou usando o argumento --silent para que o aplicativo não seja iniciado automaticamente. No entanto, a função WaitForExit () não funciona como deveria e quando tento copiar os arquivos após process. WaitForExit (), tenho erros que o diretório no AppData \ Local \ ApplicationName não é válido, porque não foi criado ainda.
Alguma idéia de por que isso está acontecendo? Existe uma maneira de aguardar o Setup. exe para finalizar a instalação e sair para realizar o que é necessário?
eeevans comentou 18 de agosto de 2017 e # 8226;
Você não pode usar Wait-Process - Name "setup"? Eu uso isso depois do --releasify para aguardar o esquilo para terminar antes de copiar a pasta Lançamentos e isso funciona.
SissiKonsta comentou 21 de agosto de 2017.
@eeevans Em primeiro lugar, obrigado pela resposta rápida. Eu não tenho certeza de que posso entender o que você está sugerindo exatamente. Eu criei o arquivo Setup. exe com --releasify e agora eu quero executá-lo, para iniciar a instalação de um aplicativo do Windows Forms e por isso estou usando o acima do código c #. O que estou tentando realizar é depois de ter instalado o aplicativo e antes de iniciá-lo para copiar alguns arquivos porque o aplicativo precisa deles para que ele possa começar. Alguma idéia do que posso fazer?
Eeevans comentou 21 de agosto de 2017.
Desculpe, não entendi o seu problema original. use Process. GetProcessByName ("setup"), em seguida,.WaitForExit () sobre isso.
SissiKonsta comentou 5 de setembro de 2017.
@veevans eu tentei isso, mas isso não funciona. Alguém tem alguma idéia de por que isso está acontecendo e como implementar o que é solicitado?
&cópia de; 2018 GitHub, Inc. Termos Privacidade Segurança Status Ajuda.
Você não pode executar essa ação neste momento.
Você fez login com outra guia ou janela. Recarregue para atualizar sua sessão. Você se separou em outra guia ou janela. Recarregue para atualizar sua sessão.

Esperando um processo com tempo limite em.
Na mesma linha da minha última publicação, podemos querer ser mais inteligentes sobre o lançamento de um processo e aguardamos a saída.
Particularmente, se esse processo for parte de um sistema crítico, como seu processo de compilação, você não quer que um processo suspenso seja capaz de fazer com que seu sistema de compilação inteiro pare de morrer nas suas faixas.
Felizmente, o Processo tem uma sobrecarga de WaitForExit que leva um tempo limite inteiro e retorna um booleano - verdadeiro se o processo for encerrado ou falso se o processo não acontecesse.
Usando esta função, podemos escrever um método como este:
Neste trecho, OutputDataReceived é um evento que dispara quando o processo grava dados em saída padrão e sinais BeginOutputReadLine para que configuramos nosso evento e estamos prontos para começar a ouvir a saída do processo.
Usar o formulário de evento neste caso significa que não precisamos ter o texto de saída completo do processo na memória em nenhum momento. À medida que o processo escreve uma linha de texto, teremos apenas essa linha na memória, e isso será coletado por lixo depois de atualizar nosso contador.
Há dois "gotcha" s neste trecho, no entanto.
O primeiro é process. Kill (). Esta é uma condição de corrida clássica - entre o tempo em que nosso processo retorna de process. WaitForExit () e invoca processo. Kill (), o processo de destino pode sair. Nesse caso, o MSDN afirma que, se você chamar. Kill () em um processo que já saiu, você receberá uma InvalidOperationException.
Podemos corrigir isso, manipulando a exceção, assim:
O segundo "gotcha" é muito sutil, e você provavelmente não o achará até que a função não retorne o resultado esperado, ou até se sentar e ler toda a página de documentação para Process. WaitForExit (int). O MDSN afirma que:
Quando a saída padrão foi redirecionada para manipuladores de eventos assíncronos, é possível que o processamento de saída não seja concluído quando esse método retornar. Para garantir que o tratamento de eventos assíncrono tenha sido concluído, chame a sobrecarga WaitForExit () que não leva nenhum parâmetro depois de receber uma verdade dessa sobrecarga.
Nesse caso, é possível que nossa função GetNumOutputChars devolva um valor que contenha menos caracteres do que a saída real do processo, a menos que chamemos WaitForExit () novamente.
Com isso em mente, nossa função de segurança final agora se parece com isto:

Code Ducky.
um blog para codificadores por codificadores.
Trabalhando com processos em.
Os idiomas de scripts e shell são geralmente construídos em torno da capacidade de um processo para iniciar facilmente e trabalhar com os resultados dos outros. Este é o principal modo de processamento em bash, enquanto o ruby ​​suporta pelo menos 5 abordagens integradas com diferentes níveis de flexibilidade e concisão.
Em, isso é uma espécie de operação normalmente é feito através da API System. Diagnostics. Process. O Process API é bastante geral e poderoso, mas pode ser complicado e difícil de usar corretamente nos casos de uso comum que são tratados tão bem pelas linguagens acima. Como um spoiler, acabei envolvendo grande parte dessa complexidade em uma nova biblioteca: MedallionShell. Com o MedallionShell, esse tipo de tarefa é um one-liner:
Mais sobre isso mais tarde, no entanto. Por enquanto, vamos voltar ao Processo. Como um exemplo concreto, recentemente queria que meu aplicativo lancasse uma instância do NodeJS para executar o compilador menos css. Eu precisava escrever na entrada padrão do Node & # 8217; ao capturar o texto de saída padrão, texto de erro padrão e código de saída.
Uma tentativa inicial.
Aqui é o código com que comecei:
Este código é bastante detalhado; infelizmente também é bastante buggy.
Lidando com os argumentos do processo.
Um dos primeiros problemas que notamos com este código é que a propriedade Arguments no ProcessStartInfo é apenas uma string. Se os argumentos que estamos passando são dinâmicos, precisaremos fornecer a lógica de escape adequada antes de concatenar para impedir que coisas como espaços em caminhos de arquivos sejam quebrados. Escapar os argumentos da linha de comando do Windows é estranhamente complexo; Felizmente, o código necessário para implementá-lo está bem documentado nesta publicação do StackOverflow. Assim, a primeira mudança que nós vamos fazer é adicionar lógica de escape:
Lidar com deadlocks.
Um problema menos óbvio é o bloqueio. Os três fluxos de processo (entrada, saída e erro) são finitos em quanto de conteúdo eles podem armazenar. Se o buffer interno for preenchido, então quem estiver escrevendo para o fluxo irá bloquear. Neste código, por exemplo, não lemos os fluxos de saída e erro até que o processo tenha saído. Isso significa que podemos encontrar-nos em um caso em que o Node esgota o buffer de erro. Nesse caso, o Nó bloquearia a gravação em erro padrão, enquanto nosso aplicativo está bloqueado a leitura até o final do padrão. Assim, nós nos encontramos em um impasse!
O Process API fornece um método que parece projetado para lidar com isso: BeginOutput / ErrorReadLine. Com este método, você pode assinar o assíncrono & # 8220; DataReceived & # 8221; eventos em vez de ler os fluxos de saída diretamente. Dessa forma, você pode ouvir ambos os fluxos ao mesmo tempo. Infelizmente, este método não fornece nenhuma maneira de saber quando o último bit de dados foi recebido. Porque tudo é assíncrono, é possível (e eu observei isso) para que os eventos disparem depois que WaitForExit () retornou.
Felizmente, podemos fornecer nossa própria solução alternativa usando Tarefas para ler asíncronamente as transmissões enquanto aguardamos o Nó para sair:
Adicionando um tempo limite.
Outra questão que gostaria de lidar é a de um processo pendurado. Em vez de esperar para que o processo saia, nosso código seria mais robusto se forçássemos um timeout em vez disso:
Async todo o caminho!
Enquanto nós agora estamos usando o IO assíncrono para ler dos fluxos do processo, ainda estamos bloqueando um segmento enquanto aguardamos o processo para concluir. Podemos melhorar a eficiência aqui, indo totalmente assíncrono:
Adaptando-se a volumes de dados maiores.
Outra questão que pode surgir ao tentar generalizar essa abordagem é a do volume de dados. Se estivermos fornecendo uma grande quantidade de dados através do processo, nós provavelmente queremos substituir as chamadas convenientes ReadToEndAsync () com loops de leitura assíncronos que processam cada pedaço de dados conforme ele vem.
Mudando para MedallionShell.
Nós já construímos um código (esperançosamente) correto, robusto e eficiente para trabalhar com um processo. No entanto, espero que este exemplo o tenha convencido de que a API do Processo não é suficiente para o trabalho quando se trata de facilidade de uso. Para esse fim, irei apresentar uma alternativa: a biblioteca MedallionShell (disponível no NuGet). Aqui, a lógica equivalente usando MedallionShell:
Com o MedallionShell, os argumentos são escapados automaticamente, os fluxos de processo são automaticamente armazenados em buffer para evitar o impasse, e tudo está bem envolvido em uma API baseada em tarefas compatível com asínc. Nós não teremos que nos preocupar em chamar Dispose (): por padrão, o Processo é descartado automaticamente após a conclusão do comando.
O MedallionShell também oferece sobrecargas do operador para permitir o redirecionamento semelhante à da entrada padrão e saída padrão. Isso significa que você pode usar & # 8220; & lt; & # 8221; e & # 8220;> & # 8221; para canalizar dados de e para fluxos, arquivos e coleções. Você pode até usar o & # 8220; | & # 8221; para canalizar dados de um objeto Command para outro.
Mike Adelson.
Últimas publicações de Mike Adelson (ver todos)
Implementando Equals () e GetHashCode () em C # 7 - 3 de junho de 2017 Scripting in C # - 3 de maio de 2017 7 maneiras de usar C # 7 throw expressions - 26 de abril de 2017.
Sobre Mike Adelson.
I & # 8217; m engenheiro de software em Applied Predictive Technologies em Washington D. C., onde trabalho em & # 8220; dados grandes & # 8221; análise e desenvolvimento web. No meu tempo livre, eu gosto de ler, trabalhar em vários projetos paralelos e responder perguntas no StackOverflow.
Pós-navegação.
7 pensamentos sobre & ldquo; Trabalhando com processos em & rdquo;
É possível ler e escrever para o mesmo processo dentro do mesmo programa. Eu usei o shell medalhão para ler a saída de um programa de console interativo. Mas quando eu iniciar um segmento diferente para escrever comandos para o programa, o writestream. writeline parece apenas pendurar. Estou tentando controlar pianobar (veja github). Há algum passo ao tentar ler uma linha do processo e responder com uma linha. Isto está me enlouquecendo.
Sim, deve ser possível ler e escrever para um processo dentro do mesmo programa. Certifique-se de que está usando a versão mais recente do MedallionShell e que a entrada padrão do comando está definida como AutoFlush (deve ser o padrão).
Você pode observar WriteLine para pendurar se o processo de destino não for puxar os dados e o buffer interprocesso for preenchido (evitando assim que o preenchimento seja concluído).
É difícil para mim dizer mais sem ver o seu código; considere postar uma descrição mais detalhada e uma amostra de código como um problema em https: // github / madelson / MedallionShell.
Obrigado Michael. Eu fiz exatamente isso, o problema # 9 #. Liguei a minha pergunta. Claramente, eu estava com muito sono para escrever qualquer coisa. Eu quis dizer que há algum passo que é necessário que eu esteja faltando. Algo óbvio para todos os outros por mim.
É possível aguardar uma string específica no fluxo de saída do comando?
bool found = await cmd. StandardOutput. Expect (searchstring, timeout);
Não há funcionalidades incorporadas para fazer isso. Se a string não abranger uma linha, você poderia fazer:
enquanto ((linha = cmd. StandardOutput. ReadLine ())! = null)
Se a cadeia de pesquisa abranger várias linhas, você pode usar uma técnica de loop semelhante, onde você acompanha os últimos N caracteres onde N é o comprimento da seqüência de pesquisa.

Herança múltipla.
Derivado de muitas coisas.
Process. WaitForExit e. Exited event aren & # 8217; t working?
. NET System. Diagnostics. Process Class & # 8211; Parte 1.
Process. WaitForExit e. Exited event aren & # 8217; t working? Eu pensei que tinha achado que isso era o caso - mas foi minha culpa, provavelmente o mesmo para você também. Eu examinarei o que encontrei ao explorar e resolver esse problema.
Resposta curta: se você estiver redirecionando StandardOutput e / ou StandardError, use os métodos assíncronos Process. BeginErrorReadLine () e. BeginOutputReadLine () ANTES de chamar. WaitForExit () e capture a saída englobando os eventos Process. ErrorDataReceived e. OutputDataReceived.
A resposta longa começa comigo usando o Visual Studio diffmerge. exe na pasta Common7 / IDE para comparar arquivos de texto no modo de lote. Estou apresentando um teste de regressão em um processo de lote iniciado por compilação. Eu precisava de uma ferramenta que cuspiria um arquivo de diferença de texto ao comparar dois arquivos (não um arquivo de resultado de mesclagem). O WinMerge e a Beyond Compare estão à minha disposição, mas eles não parecem produzir nada além de resultados mesclados (o que normalmente é o que eu quero, mas não desta vez).
Minha estrutura de regressão chamará diffmerge. exe e armazenará o arquivo diff resultante para posterior revisão. Codifiquei o meu ProcessStartInfo ...
Segui-se com o início do processo e aguardando o fim do processo ... e aguardando ... aguarde espera ...
Isso me fez ler o MSDN e cavar mais fundo no uso da classe Process. Descobri algumas informações interessantes, provavelmente deveria ter sido óbvio.
Primeiro, descobri que, às vezes, executando meu Diferente processo infantil com diferentes argumentos funcionavam, às vezes não o fazia, tornando a questão misteriosa.
Em segundo lugar, achei que funcionou bem quando eu não redirecionei a saída.
Então, obviamente, estava sentindo falta de algo. Eu precisava realmente ler os Doccs da API de Processo e, assim, achei esse nugget: Artigo MSDN.
Depois de encontrar e ler esse artigo do MSDN, entendi. O meu exemplo de código acima funcionará se o buffer StdOut ou StdError não preencher. No entanto, o que eu estava vendo era o buffer StdOut preenchido, o Processo Infantil foi bloqueado na próxima gravação StdOut / StdError, o Processo Principal estava esperando infinitamente no Processo Criança para sair antes de ler o buffer StdOut / StdError. Para mim, parecia que o método WaitForExit e / ou o evento Exited estão quebrados / não apanhando o processo filho que sai, no entanto, era meu código que estava quebrado.
Eu modifiquei o código para usar os métodos assíncronos e, de repente, meus problemas desapareceram. Não há mais bloqueio, tudo funcionou conforme o esperado.
Eu usei StringBuilders como buffers para armazenar os dados recebidos nos eventos.
Na parte 2, eu me deparo com as implementações Process StdOut / StdError ReadLine em torno de minhas necessidades específicas, eu entro em como resolvi esse problema.

No comments:

Post a Comment