Eu uso Process. Start para iniciar um arquivo em lote. O arquivo em lote usa o comando START para iniciar vários programas em paralelo e depois sai. Uma vez que o arquivo em lotes é concluído Process. HasExited torna-se verdadeiro e Process. ExitCode contém o código de saída correto. Mas quando chamo Process. WaitForExit (), ele trava nunca retorna. O seguinte fragmento de código demonstra o problema. Ele cria um arquivo em lotes, o inicia e depois imprime: Ele deve imprimir: mas nunca o faz (mesmo que HasExited seja verdadeiro e já temos um ExitCode). Notei que isso só ocorre quando o arquivo em lotes contém comandos START e quando a saída padrão e o erro padrão são redirecionados. Por que WaitForExit () nunca retorna O que é o caminho certo para aguardar o encerramento de um processo desse tipo É seguro apenas pesquisar Process. HasExited ou pode resultar em outros problemas PS. Acabei de notar que chamar WaitForExit (100000) com um tempo limite enorme (que definitivamente não expira) retorna imediatamente quando o processo sai. Wierd. Sem tempo limite, ele trava. Existe uma diferença fundamental quando você chama WaitForExit () sem tempo limite, ele garante que o stdouterr redirecionado tenha retornado EOF. Isso garante que você tenha lido toda a saída que foi produzida pelo processo. Nós não podemos ver o que o quotonOutputquot faz, mas as chances de que ele impede o seu programa porque ele faz algo desagradável como assumir que seu segmento principal está ocioso quando ele está realmente preso em WaitForExit (). Ndash Hans Passant 3 nov 14 às 12:06 Isso parece ser um artefato (Id say bug) na implementação específica do tratamento assíncrono baseado em eventos do StandardOutput e do StandardError. Percebi que, enquanto consegui reproduzir facilmente o seu problema, simplesmente executando o código que você forneceu (excelente exemplo de código, a propósito.)), O processo realmente não era suspenso indefinidamente. Em vez disso, ele retornou de WaitForExit () uma vez que ambos os processos filho que tinham sido iniciados já haviam saído. Isso parece ser uma parte intencional da implementação da classe Process. Em particular, no método Process. WaitForExit (), uma vez que terminou de aguardar o processo, ele verifica se um leitor para stdout ou stderr foi criado se assim for, e se o valor de tempo limite para o WaitForExit ( ) Chamada é infinita (ou seja, -1), o código realmente espera o fim do fluxo no (s) leitor (es). Cada leitor respectivo é criado somente quando o método BeginOutputReadLine () ou BeginErrorReadLine () é chamado. Os fluxos stdout e stderr não estão fechados até que os processos filho tenham fechado. Então, esperando no final desses fluxos irá bloquear até que isso aconteça. Que WaitForExit () deve se comportar de forma diferente, dependendo se um tenha chamado qualquer um dos métodos que iniciam a leitura baseada em eventos dos fluxos ou não, e especialmente porque a leitura desses fluxos diretamente não causa WaitForExit () para comportar-se desse jeito, cria Uma inconsistência na API que torna muito mais difícil de entender e usar. Enquanto eu pessoalmente chamo isso de bug, suponho que é possível que o implementador (es) da classe Process esteja ciente dessa inconsistência e criou isso de propósito. Em qualquer caso, o trabalho seria ler StandardOutput e StandardError diretamente em vez de usar a parte baseada em eventos da API. (Embora, é claro, se o código estivesse esperando nesses fluxos, verificaria o mesmo comportamento de bloqueio até que o filho fique próximo.) Por exemplo (C, porque eu não conheço F o suficiente para tapar um exemplo de código assim juntado rapidamente :)): Espero que o trabalho acima ou algo semelhante abordará o problema básico em que você se encontrou. Meus agradecimentos ao comentarista Niels Vorgaard Christensen por dirigir-me para as linhas problemáticas no método WaitForExit (), para que eu possa melhorar esta resposta. De uma linha de comando, posso executar o msbuild com sucesso: c: windowsmicrosoftframeworkv4.0.30319msbuild. exe helloworld. csproj T: Build Quando eu executar o equivalente a partir do programa AC, usando a classe Process, msbuild retorna um erro dizendo que a estrutura não foi encontrada. O erro diz para definir a chave de registro SDKInstallRootv2.0. Como executar msbuild a partir de c string de código exePath System. IO. Pathbine (quotc: windowsmicrosoftframeworkv4.0.30319quot, quotmsbuild. exequot) Processo p novo Processo () p. StartInfo. FileName exePath p. StartInfo. WindowStyle ProcessWindowStyle. Normal p. StartInfo. Argumentos quothelloworld. csproj t: Buildquot p. StartInfo. WorkingDirectory quotc: msbuildhelloworldquot p. StartInfo. RedirectStandardError true p. StartInfo. RedirectStandardOutput true p. StartInfo. UseShellExecute falso p. Start () p. WaitForExit () erros de cadeia p. StandardError. ReadToEnd () String output p. StandardOutput. ReadToEnd () Sexta-feira, 04 de fevereiro de 2011 15:40 Obrigado pela sua postagem. Parece que você não configurou a chave de registro do SDKInstallRootv2.0, você pode tentar verificar se há uma chave NamequotSDKInstallRootv2.0quot com DataquotC: WINDOWSMicrosoftFrameworkv2.0.50727quot no diretório HKLMSoftwareMicrosoftFramework No entanto, se você quiser criar o projeto por meio de programação, acho que o A melhor abordagem é fazê-lo com buildengine. Você pode tentar o código Chaos na seguinte publicação. Espero que a minha resposta ajude. Suporte ao assinante do MSDN no Fórum Se você tiver algum comentário sobre o nosso suporte, entre em contato com msdnmg microsoft Ziwei Chen MSFT MSDN Community Support Feedback para nós Obter ou solicitar um exemplo de código da Microsoft Lembre-se de marcar as respostas como respostas se eles ajudam e desmarcar se eles Não forneça ajuda. Marcado como resposta por Steve Richter segunda-feira, 07 de fevereiro de 2011 15:15 segunda-feira, 07 de fevereiro de 2011 5:19
Comments
Post a Comment