Monday 13 November 2017

Waitforexit hasexited


O código parece quase isso: como você pode ver, o código inicia um processo cmd. exe e passa para ele o comando que quero ser executado. Eu redireciono StandardError e StandarOutput para lê-los a partir do código. O código lê-los antes do processo. WaitForExit (Timeout) chamada conforme recomendado pela Microsoft (mais sobre isso mais tarde). O problema surge se o comando que eu envio para cmd. exe nunca termina ou trava indefinidamente. 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 na linha Output. StandardOutput. ReadToEnd () do processo de saída porque não conseguiu 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 durante anos e, em seguida, é suspenso repentinamente sem nenhum motivo aparente. Antes de escrever, recomendava ler fluxos redirecionados antes do processo. WaitForExit (Timeout), bem, isso é especialmente verdadeiro se você usar a assinatura WaitForExit sem o tempo limite. Se você chamar processo. WaitForExit () antes de ler os fluxos redirecionados: código 2: você pode enfrentar um impasse se o comando que você anexar ao cmd. exe ou o processo que você está chamando preencher a saída padrão ou erro padrão. Isso porque nosso código não pode atingir as linhas de processo de saída. StandardOutput. ReadToEnd () De fato, 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 lê os buffers preenchidos dos fluxos e isso não pode acontecer porque o código está pendurado em A 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: o primeiro script escreve 4096 bytes para a saída padrão e o segundo para erro padrão. Salve um destes em C: testbuffsize. bat e execute o processo de chamada do nosso programa. WaitForExit () antes do processo de saída. StandardOutput. ReadToEnd () como no código 2. Você pode fazê-lo escrevendo CommandResult Resultado ExecuteShellCommandSync (c: testbuffsize. bat, 1000) na linha 13 do código 1. O código não irá pendurar, mas se você escrever um byte mais em qualquer um dos dois fluxos, ele irá transbordar o tamanho do buffer tornando o programa aguentar. Se você precisa redirecionar e ler a saída padrão ou o erro padrão, a melhor solução é lê-los de forma assíncrona. Uma excelente maneira de fazer isso é proposta por Mark Byers neste segmento stackoverflow. Como a última coisa, observe que, se o processo filho sair apenas porque você usa o processo. WaitForExit (Timeout) assinatura e ele realmente vai no tempo limite, você deve matar o processo cmd. exe e seus possíveis filhos. Tenho observado que Process. HasExited às vezes retorna verdadeiro mesmo que o processo ainda esteja em execução. Meu código abaixo inicia um processo com o nome testprogram. exe e depois espera que ele seja encerrado. O problema é que, às vezes, eu sou jogado a exceção, parece que mesmo que HasExited retorna verdadeiro, o processo em si ainda está vivo no sistema - como isso pode ser o meu programa grava em um arquivo de log antes que ele termine e, portanto, eu preciso ser absolutamente Certifique-se de que este arquivo de log existe (aka o processo foi encerrado) antes de lê-lo. A verificação contínua de sua existência não é uma opção. UPDATE: Eu apenas tentei aguardar com process. WaitForExit () em vez do loop de pesquisa e o resultado é exatamente o mesmo. Adição: o código acima era apenas para demonstrar um problema mais claro. Para deixar claro o meu problema, não é que eu ainda consigo segurar o processo por Process. GetProcessesByName (testprogram) depois de definir HasExited como verdadeiro. O problema real é que o programa que estou executando externamente escreve um arquivo - apenas antes - ele termina (graciosamente). Eu uso HasExited para verificar quando o processo terminou e, portanto, eu sei que posso ler o arquivo (porque o processo foi encerrado), mas parece que HasExited retorna verdadeiro mesmo às vezes, quando o programa ainda não escreveu o arquivo no disco. Heres código de exemplo que ilustra o problema exato: perguntou 25 de março 10 às 21:52 johnrl I39m perguntando se tudo vai como você pensa que eles vão. Nunca tive problemas em gerenciar processos como este. Talvez ele comece um processo filho e saia o principal, ou as mudanças pid por algum motivo, ou o despejo é feito em outro processo, pois ele funciona no relatório de erros do Windows ou. Existem muitas variáveis. Você pode usar procmon (sysinternals) para obter mais informações sobre o processo faz o que e verificar se pid39s no process Explorer (procexp de sysinternals) por favor ndash atlaste 18 de janeiro 13 às 7:20 11 Respostas Eu percebo que este é um post antigo, mas em Minha busca para descobrir por que meu aplicativo executando o evento Exitado antes do aplicativo ter aberto mesmo descobri algo que eu poderia ser útil para as pessoas que enfrentam esse problema no futuro. Quando um processo é iniciado, é atribuído um PID. Se o Usuário for solicitado com a caixa de diálogo Controle de Conta de Usuário e selecionando Sim, o processo será reiniciado e atribuído um novo PID. Eu me sentei com isso por algumas horas, espero que isso possa salvar algum tempo. Respondeu 22 de outubro 14 às 13:11 Eu sugiro que você tente assim: de qualquer forma. Na página MSDN do HasExited Im lendo a seguinte nota destacada: 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 essa propriedade retornar verdadeira. Para garantir que o tratamento de eventos assíncrono tenha sido concluído, chame a sobrecarga WaitForExit () que não leva nenhum parâmetro antes de verificar HasExited. Isso pode ser de alguma forma relacionado ao seu problema, pois você está redirecionando tudo. Respondeu 15 de janeiro 13 às 15:52 Eu sei, esta é uma postagem antiga, mas eu posso ajudar alguém. A classe Process class às ​​vezes HasExited retornará true se o processo tiver saído ou se o processo for executado com privilégios de administrador e seu programa tiver apenas privilégios de usuário. Respondeu Jan 4 15 às 20:56 Então, apenas para uma investigação mais aprofundada sobre a causa raiz do problema, você talvez verifique o que realmente está acontecendo usando o Process Monitor. Basta iniciá-lo e incluir o programa externo e sua própria ferramenta e deixá-lo registrar o que acontece. Dentro do log você deve ver como a ferramenta externa grava no arquivo de saída e como você abre esse arquivo. Mas dentro deste log você deve ver em qual ordem todos esses acessos acontecem. A primeira coisa que me veio à cabeça é que a classe Process não mora e o processo realmente desapareceu quando diz isso. Então, o problema é que, neste momento, parece que o arquivo ainda não está totalmente disponível. Eu acho que este é um problema do SO. Porque ele mantém algumas partes do arquivo ainda dentro de um cache que não está totalmente escrito no disco e a ferramenta simplesmente saiu sem lavar o arquivo. Com isso em mente, você deve ver dentro do log que a ferramenta externa criou o arquivo, expirou e APÓS que o arquivo será fechado (pelo sistema operacional talvez remova todos os filtros quando você encontrou este ponto dentro do log). Então, se minhas suposições estiverem corretas, a causa raiz seria o mau comportamento de sua ferramenta externa, que você não pode mudar, levando a simplesmente esperar um pouco depois do processo ter saído e esperar que o tempo limite seja longo o suficiente para obter o arquivo fechado pela SO (talvez tente abrir o arquivo em um loop com um tempo limite até que ele tenha êxito). Respondeu em 16 de janeiro às 12:36 Primeiramente, você está certo de que testprogram não engendra um processo próprio e saia sem esperar que esse processo termine. Estão lidando com algum tipo de condição de corrida aqui, e o testprogram pode ser significativo. O segundo ponto que a Id gostaria de fazer é sobre isso - preciso ter certeza absoluta de que este arquivo de log existe. Bem, não existe tal coisa. Você pode fazer seu cheque, e então o arquivo desapareceu. A maneira comum de resolver isso não é verificar, mas sim fazer o que você quer fazer com o arquivo. Vá em frente, lê-lo, capture exceções, tente novamente se o item parece instável e você não quer mudar nada. O check-and-do funcional não funciona bem se você tiver mais de um ator (thread ou o que quer que seja) no sistema. Um monte de idéias aleatórias segue. Você tentou usar o FileSystemWatcher e não dependendo da conclusão do processo. Isso é melhor se você tentar ler o arquivo (não verificando se ele existe, mas atuando em vez disso) no processo. Evento exato que ele não deveria. O sistema é saudável Qualquer coisa suspeita no Evento Log Pode alguma política de antivírus realmente agressiva estar envolvida (não pode contar muito sem ver todo o código e procurar no testprogram.) Respondeu Jan 17 13 às 21:46 Para começar, há um problema com o uso de Process. WaitForExit ao invés de buscá-lo de qualquer maneira , É tecnicamente possível que o processo saia de um ponto de vista utilizável, mas o processo ainda está em breve enquanto ele faz coisas como o cache do disco descarregado. É o arquivo de log especialmente grande (ou qualquer operação que está executando pesado em gravações de disco) respondeu 25 de março 10 às 21:56 O tamanho máximo absoluto de logfiles é de cerca de 1mb. A razão pela qual eu uso polling é que eu preciso para abortar a tarefa de espera a qualquer momento e com WaitForExit estou bloqueado pelo menos até o tempo limite. Na sua opinião, de fato, é possível que o programa esteja esvaziando os fluxos do seu disco para o disco, mesmo que HasExited retorna verdadeiro. Eu simplesmente acho estranho que o processo não esteja completamente aninhado na lista de processos quando o HasExited for verdadeiro. Não menciona quaisquer circunstâncias especiais na documentação, tanto quanto eu posso dizer. Ndash johnrl 25 mar 10 às 22:03 É algo que eu já vi antes, mas não para tamanhos tão pequenos. Conforme apontado por outro comentarista, a classe Processo manterá uma referência ao processo, você pode querer chamar Dispose na instância do processo depois de verificar a saída, mas antes de tentar encontrá-la na lista de processos. Ndash tyranid 26 de março 10 às 3:35 Eu só tenho uma única instância em execução e eu tentei manter o Gerenciador de tarefas do Windows aberto e assistindo a lista de processos (também verificando os ID39s, eles combinam) e, de fato, quando meu código lança a exceção O processo ainda está na lista. Às vezes, ele sai quase instantaneamente quando a exceção é jogada, outras vezes pode demorar um segundo ou dois a desaparecer. Eu não tenho certeza se o Gerenciador de Tarefas pode ser confiável (atraso talvez), mas o fato é que meu código lança a exceção - nem sempre, mas em torno da 110ª das execuções que faz. Ndash johnrl 25 de março 10 às 22:10 Uma vez que process. HasExited é verdadeiro, o processo foi encerrado. Está morto. Pode ser um zumbi por algum período de tempo, especialmente se houver alças abertas para o objeto de processo. O fato de que GetProcessByName () pode às vezes retornar esse processo significa que nada além do processo ainda é um zumbi. Você deve processar. Dispor () para garantir que esse identificador seja liberado. Mas seu quottestquot usando GetProcessByName simplesmente não é uma coisa razoável a fazer. Process. HasExited é o único teste confiável que você pode fazer, e você já conseguiu. Ndash John Knoeller 26 de março 10 às 9:01 Parece razoável. Mas eu não entendo como é que o arquivo 39testprogram39 escreve (o que é feito antes de fechar), não é escrito em disco quando HasExited é verdadeiro. Como isso pode ser se o processo for um zumbi (então deveria ter descarregado tudo no disco, à direita). Eliminar o objeto de processo não tem efeito no programa executado pelo processo tanto quanto eu sei, então, como isso ajudaria ndash johnrl 26 de março às 13:05 Se um identificador estiver aberto ao processo, o sistema operacional liberará a memória do processo quando O processo foi encerrado, mas mantém informações administrativas sobre o processo, como o identificador, o código de saída e o tempo de saída. Provavelmente não está relacionado, mas vale a pena notar. Se é apenas um problema 110 do tempo e o processo desaparece depois de um segundo, de qualquer maneira, dependendo do seu uso do HasExited, tente adicionar outro atraso após a verificação HasExited, como e veja se o problema persiste. Pessoalmente, sempre usei o manipulador de eventos Exited em vez de qualquer tipo de pesquisa e um wrapper personalizado simplista em torno de System. Diagnostics. Process para lidar com coisas como segurança de thread, envolvendo uma chamada para CloseMainWindow () seguido de WaitForExit (tempo limite) e, finalmente, Matar(). Log, etc., e nunca encontrou um problema. Respondeu 25 de março 10 às 22:34 Talvez o problema esteja no testprogram Este código gentilmente flushclose etc. Parece-me se testprogram escreve um arquivo no disco, o arquivo deve, pelo menos, estar disponível (vazio ou não) atendido 29 de abril 10 Às 8:27 Se você tiver aplicação na web e seu processo de programa externo está gerando arquivos (escreva para o disco), verifique se o IIS tem direitos para escrever para essa pasta, se não estiver na propriedade, adicione permissão de segurança para seu usuário do IIS, esse foi o motivo em Meu caso, eu estava recebendo o processo. HasExited verdadeiro, mas os arquivos produzidos do processo não foram concluídos, depois de lutar por um tempo eu adicionei permissões completas à pasta onde o processo estava contorcendo-se e processou. Refresh () como Zarathos descrito acima e tudo Estava funcionando como esperado. Respondeu Apr 18 14 às 0:16 Use processname. Refresh () antes de verificar se o processo foi encerrado ou não. Refresh () irá limpar todas as informações em cache relacionadas ao processo. Respondeu 30 de abril 15 às 7:44 Eu vejo que isso foi abatido - qualquer visão sobre o motivo pelo qual eu tenho uma questão semelhante ao OP e estou apenas tentando classificar todas essas respostas. Ndash Kevin Holt 22 nov 16 às 18:28 Sua resposta 2017 Stack Exchange, Inc

No comments:

Post a Comment