C # waitforexit child process


Processo filho Cfore waitforexit
Obter através da App Store Leia esta publicação em nosso aplicativo!
Aguarde até um processo terminar.
Eu tenho um aplicativo que faz.
para iniciar outro aplicativo 'ABC'. Eu quero aguardar até que o aplicativo final (processo morre) e continuar minha execução. Como eu posso fazer isso?
Pode haver várias instâncias do aplicativo 'ABC' executando ao mesmo tempo.
Eu acho que você só quer isso:
Consulte a página MSDN para o método. Também tem uma sobrecarga onde você pode especificar o tempo limite, então você não está esperando potencialmente para sempre.
Use Process. WaitForExit? Ou assine o evento Process. Exited se você não quer bloquear? Se isso não fizer o que você quer, por favor nos dê mais informações sobre seus requisitos.
Faço o seguinte na minha aplicação:
Há alguns recursos extras lá que você pode achar úteis.
Você pode usar a espera para sair ou você pode pegar a propriedade HasExited e atualizar sua UI para manter o usuário "informado" (gerenciamento de expectativa):

Processo filho Cfore waitforexit
Obter através da App Store Leia esta publicação em nosso aplicativo!
Como aguardar um processo e todos os seus processos filho para sair?
Existe um método de espera que retornaria quando o processo de destino e todos os seus subprocessos fossem encerrados? Parece Process. WaitForExit () apenas aguardar no processo de destino.
Isso pode ajudar um pouco - o Windows 2000 introduziu o conceito de "trabalho", que é uma coleção de processos controlados como uma unidade, bem como um grupo de processos no UNIX / LINUX. Então, você pode matar um processo e todos os seus filhos, iniciando o processo em um trabalho e depois informando o Windows para matar todos os processos no trabalho.
Basicamente, crie um novo emprego e use o trabalho para gerar o processo filho. Todos os seus filhos também serão criados no novo trabalho. Quando você expirar, basta chamar o método kill () do trabalho e toda a árvore do processo será encerrada. Você pode verificar a documentação para obter mais informações sobre isso. Usei a API Win32 :: Job do Perl para alcançar o que você está tentando fazer. Confira o seguinte link no MSDN para obter mais informações: Job API Description.
A resposta desta pergunta mostra como matar todos os subprocessos de um processo de forma recursiva. Em vez de matá-lo, você pode aguardar por cada subprocesso até terminar. Você pode usar o evento Process. Exited conforme descrito nesta pergunta, que parece uma duplicação para este.
Existe um erro que dará o comportamento que você está procurando.
WaitForExit () aguardará todos os processos filho se você estiver lendo a saída de forma assíncrona.
WaitForExit (Int32.MaxValue-1) nos permite obter o comportamento normal ao usar o modo assíncrono.

Processo filho Cfore waitforexit
Obter através da App Store Leia esta publicação em nosso aplicativo!
Mate o processo filho quando o processo pai é morto.
Estou criando novos processos usando a classe System. Diagnostics. Process do meu aplicativo.
11 Respostas.
Application. Quit () e Process. Kill () são possíveis soluções, mas provaram ser pouco confiáveis. Quando o aplicativo principal morre, você ainda fica com processos filho em execução. O que realmente queremos é que os processos filho morram assim que o processo principal morrer.
A idéia é criar um "objeto de trabalho" para o seu aplicativo principal e registrar seus processos filho com o objeto de trabalho. Se o processo principal morrer, o sistema operacional cuidará de encerrar os processos filho.
Olhando para o construtor.
A chave aqui é configurar o objeto do trabalho corretamente. No construtor, estou configurando os "limites" para 0x2000, que é o valor numérico para JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
O MSDN define esta bandeira como:
Causa todos os processos associados ao trabalho para terminar quando o último identificador para o trabalho está fechado.
Uma vez que esta classe está configurada. Você só precisa registrar cada processo infantil com o trabalho. Por exemplo:
Esta publicação destina-se a ser uma extensão da resposta de Matt Howells, especificamente para aqueles que se deparam com o uso de Job Objects sob Vista ou Win7, especialmente se você receber um erro de acesso negado ('5') ao chamar AssignProcessToJobObject.
Para garantir a compatibilidade com o Vista e o Win7, adicione o seguinte manifesto ao processo pai:
Observe que, quando você adicionar um novo manifesto no Visual Studio 2012, ele irá conter o fragmento acima já, então você não precisa copiá-lo de ouvir. Também incluirá um nó para o Windows 8.
Sua associação de trabalho falhará com um erro de acesso negado se o processo que você está iniciando já estiver associado a outro trabalho. Insira o Assistente de compatibilidade de programas, que, começando no Windows Vista, irá atribuir todos os tipos de processos a seus próprios trabalhos.
No Vista, você pode marcar seu aplicativo para ser excluído da PCA simplesmente incluindo um manifesto de aplicação. O Visual Studio parece fazer isso para aplicativos automaticamente, então você está bem lá.
Um simples manifesto já não o corta no Win7. [1] Lá, você precisa especificar especificamente que você é compatível com o Win7 com a tag em seu manifesto. [2]
Isso me levou a me preocupar com o Windows 8. Será que vou ter que mudar meu manifesto mais uma vez? Aparentemente, há uma pausa nas nuvens, já que o Windows 8 agora permite que um processo pertença a vários trabalhos. [3] Então eu ainda não testei isso, mas imagino que essa loucura acabará agora se você simplesmente incluir um manifesto com as informações suportadas.
Dica 1: se você estiver desenvolvendo um aplicativo com o Visual Studio, como eu estava, aqui [4] são algumas boas instruções sobre como personalizar seu manifesto do aplicativo.
Dica 2: tenha cuidado com o lançamento do seu aplicativo a partir do Visual Studio. Descobri que, depois de adicionar o manifesto apropriado, eu ainda tive problemas com o PCA ao iniciar do Visual Studio, mesmo que eu usei o Start sem Debugging. No entanto, o lançamento do meu aplicativo do Explorer funcionou. Depois de adicionar manualmente devenv para exclusão da PCA usando o registro, iniciar aplicativos que usaram o Job Objects da VS também começaram a funcionar. [5]
Dica 3: se você quiser saber se o PCA é o seu problema, tente iniciar o seu aplicativo a partir da linha de comando ou copie o programa para uma unidade de rede e execute-o a partir daí. O PCA é automaticamente desabilitado nesses contextos.
Esta resposta começou com a excelente resposta de Matt Howells e outros (veja os links no código abaixo). Melhorias:
Suporta 32 bits e 64 bits. Corrige alguns problemas na resposta de Matt Howells: o pequeno vazamento de memória do extendedInfoPtr. O erro de compilação 'Win32' e uma exceção da pilha não desequilibrada eu recebi a chamada para CreateJobObject (usando o Windows 10, Visual Studio 2015, 32 bits). Nomeia o trabalho, então, se você usa o SysInternals, por exemplo, você pode encontrá-lo facilmente. Tem uma API um tanto simples e menos código.
Veja como usar este código:
Para suportar o Windows 7, é necessário:
No meu caso, não precisava suportar o Windows 7, então eu tenho uma verificação simples no topo do construtor estático abaixo.
Testei cuidadosamente as versões de 32 bits e 64 bits das estruturas, comparando as versões gerenciadas e nativas com o mesmo programa (o tamanho geral, bem como as compensações para cada membro).
Testei esse código no Windows 7, 8 e 10.
Aqui está uma alternativa que pode funcionar para alguns quando você controla o código que o processo filho é executado. O benefício dessa abordagem é que não requer nenhuma chamada nativa do Windows.
A idéia básica é redirecionar a entrada padrão da criança para um fluxo cujo outro fim está conectado ao pai e usar esse fluxo para detectar quando o pai desapareceu. Quando você usa System. Diagnostics. Process para iniciar a criança, é fácil garantir que sua entrada padrão seja redirecionada:
E então, no processo infantil, aproveite o fato de que Read s do fluxo de entrada padrão sempre retornará com pelo menos 1 byte até o fluxo estar fechado, quando eles começarão a retornar 0 bytes. Um esboço do jeito que eu terminei fazendo isso é abaixo; meu caminho também usa uma bomba de mensagem para manter o segmento principal disponível para outras coisas além de assistir padrão, mas esta abordagem geral poderia ser usada sem bombas de mensagens também.
Aconselha-se a esta abordagem:
o filho. exe real que é iniciado deve ser um aplicativo de console, portanto, ele permanece anexado a stdin / out / err. Como no exemplo acima, adaptei facilmente a minha aplicação existente que usava uma bomba de mensagem (mas não mostrava uma GUI) apenas criando um pequeno projeto de console que referia o projeto existente, instanciando o contexto do aplicativo e chamando o Application. Run () dentro do método principal do console. exe.
Tecnicamente, isso simplesmente sinaliza o processo filho quando o pai sai, então ele funcionará se o processo pai saiu normalmente ou é quebrou, mas ainda está até os processos filho para executar seu próprio desligamento. Isso pode ou não ser o que você deseja.
Existe outro método relevante, fácil e efetivo, para finalizar processos filho no término do programa. Você pode implementar e anexar um depurador deles a partir do pai; Quando o processo pai termina, os processos filho serão mortos pelo sistema operacional. Pode ir em ambos os lados anexando um depurador ao pai da criança (note que você só pode anexar um depurador por vez). Você pode encontrar mais informações sobre o assunto aqui.
Aqui você tem uma classe de utilitário que lança um novo processo e atribui um depurador a ele. Ele foi adaptado desta postagem por Roger Knapp. O único requisito é que ambos os processos precisam compartilhar o mesmo bitness. Você não pode depurar um processo de 32 bits de um processo de 64 bits ou vice-versa.
Uma maneira é passar o PID do processo pai para a criança. A criança pesquisará periodicamente se o processo com o pid especificado não existe ou não. Se não, ele acabará de sair.
Você também pode usar o método Process. WaitForExit no método filho para ser notificado quando o processo pai terminar, mas pode não funcionar no caso do Gerenciador de Tarefas.
Vejo duas opções:
Se você sabe exatamente o que o processo infantil pode ser iniciado e você tem certeza de que eles só são iniciados a partir do seu processo principal, então você poderia considerar simplesmente buscá-los pelo nome e matá-los. Transforme todos os processos e mate todos os processos que tenham seu processo como pai (acho que você precisa primeiro matar os processos filho). Aqui é explicado como você pode obter o ID do processo pai.
Eu criei uma biblioteca de gerenciamento de processo filho onde o processo pai e o processo filho são monitorados devido a um tubo WCF bidirecional. Se o processo filho terminar ou o processo pai terminar, o outro é notificado. Há também um auxiliar de depuração disponível que atribui automaticamente o depurador VS ao processo filho iniciado.
Ligue o job. AddProcess melhor para fazer após o início do processo:
Ao chamar AddProcess antes do término, os processos filho não são mortos. (Windows 7 SP1)
Eu estava procurando uma solução para este problema que não requeria código não gerenciado. Eu também não consegui usar o redirecionamento padrão de entrada / saída porque era um aplicativo do Windows Forms.
Minha solução era criar um pipe nomeado no processo pai e, em seguida, conectar o processo filho ao mesmo pipe. Se o processo pai sair, o tubo fica quebrado e a criança pode detectar isso.
Abaixo está um exemplo usando duas aplicações de console:
Criança.
Use manipuladores de eventos para fazer ganchos em alguns cenários de saída:

Processo filho Cfore waitforexit
cmd / c randomscript. cmd.
* mata um emprego pelo seu PID.
* e todos os filhos associados.
bool public killProcess (int pid)
bool didIkillAnybody = false;
Processo [] procs = Process. GetProcesses ();
para (int i = 0; i & lt; procs. Length; i ++)
se (GetParentProcess (procs. Id) == pid)
* O bem disso.
* é que também mataremos.
* qualquer criança para o processo infantil! ; o)
* isso será um porco de memória?
se (killProcess (procs. Id) == true)
* basicamente, o fato de que matamos toda a criança.
* poderia ter DEVASTADO o pai que, infelizmente,
* poderia ter cometido suicídio!
Processar myProc = Process. GetProcessById (pid);
captura (exceção ex)
Logger log = new Logger ();
log. Write (& quot; Exception catch at JobExecution. killProcess () & quot ;, ex. Message, System. Diagnostics. EventLogEntryType. Warning, false);
* Obter processo pai para um determinado PID.
private int GetParentProcess (int Id)
int parentPid = 0;
usando (ManagementObject mo = new ManagementObject (& quot; win32_process. handle = '& quot; + Id. ToString () + & quot;' & quot;))
Este outro tópico que postei realmente me ajudou:
Todas as respostas.
C: \ Documents and Settings \ Administrator & gt; taskkill / PID 4316 / T / F.
SUCESSO: o processo com PID 2124 (processo filho do PID 4316) foi encerrado.
SUCESSO: o processo com PID 4316 (processo filho do PID 792) foi encerrado.
* mata um emprego pelo seu PID.
* e todos os filhos associados.
bool public killProcess (int pid)
bool didIkillAnybody = false;
Processo [] procs = Process. GetProcesses ();
para (int i = 0; i & lt; procs. Length; i ++)
se (GetParentProcess (procs. Id) == pid)
* O bem disso.
* é que também mataremos.
* qualquer criança para o processo infantil! ; o)
* isso será um porco de memória?
se (killProcess (procs. Id) == true)
* basicamente, o fato de que matamos toda a criança.
* poderia ter DEVASTADO o pai que, infelizmente,
* poderia ter cometido suicídio!
Processar myProc = Process. GetProcessById (pid);
captura (exceção ex)
Logger log = new Logger ();
log. Write (& quot; Exception catch at JobExecution. killProcess () & quot ;, ex. Message, System. Diagnostics. EventLogEntryType. Warning, false);
* Obter processo pai para um determinado PID.
private int GetParentProcess (int Id)
int parentPid = 0;
usando (ManagementObject mo = new ManagementObject (& quot; win32_process. handle = '& quot; + Id. ToString () + & quot;' & quot;))
Este outro tópico que postei realmente me ajudou:
Stacktrace: no System. Management. ManagementException. ThrowWithExtendedInfo (ManagementStatus errorCode)
Eu achei esse código funcionar para mim:
Proposta como resposta por Fuzzy. Logician Sexta-feira, 09 de março de 2012 20h40.
Process KillerP = novo Processo ();
Proposto como resposta por Magnum_2007 quinta-feira, 30 de agosto de 2012 12:28.
Não adianta o nome da rotina familiar: uma pequena modificação do KillProcessAndChildren de RonaldDev.
privar void Familicide (int pid)
// mata uma árvore de processo (família)
// este código requer a referência para System. Managemnt. dll.
// Se uma abordagem recursiva direta é usada, do que é possível perder as crianças criadas entre a chamada.
// Família e solicitar a lista de crianças através do pesquisador.
System. Management. ManagementObjectSearcher searcher = novo System. Management. ManagementObjectSearcher (& quot; Select * From Win32_Process Onde ParentProcessID = & quot; & # 43; pid);
System. Management. ManagementObjectCollection moc = searcher. Get;
foreach (System. Management. ManagementObject mo in moc)
// processo já encerrado, então, obter Item (& quot; ProcessID & quot;) aumentará um erro.
Processar aProcess = Process. GetProcessById (pid);
> catch (ArgumentException ex)
// processo já encerrado.
foreach (Int32 aChildPid em pids)
A Microsoft está conduzindo uma pesquisa on-line para entender sua opinião sobre o site da Msdn. Se você optar por participar, a pesquisa on-line será apresentada quando você deixar o site Msdn.

C # Hoje.
Deixe o # C # hoje!
Deixe o # C # hoje!
Como executar o processo filho no mesmo console em C #
Muitas vezes eu ouço perguntas sobre como executar subprocessos na consola dos pais. As pessoas ficaram confusas sobre como garantir que o processo filho use o mesmo console que o pai.
Às vezes eles tentam redirecionar a saída padrão apenas para despejá-lo para console via Console. Write. Isso é muito esforço que não é necessário se a única coisa necessária é usar o mesmo console - não verificar a saída.
A maneira correta de executar o processo filho no console do pai é configurar a propriedade UseShellExecute da classe ProcessStartInfo. Vamos considerar um exemplo que executa o comando do tempo. Por que o tempo? Porque ele lê da entrada padrão. Desta forma, você saberá qual console ele usa.
Você pode ver que o processo filho está abrindo um novo console.
Isso não é o que queríamos. Nós deixamos o valor padrão do UseShellExecute, o que é verdadeiro. Isso significa que um shell será usado para o processo filho. Usar shell significa que um novo console será criado.
Vamos mudar o valor de UseShellExecute para falso.
Desta vez, apenas um console é usado.
Isso é tudo o que é necessário para redirecionar todos os fluxos de entrada / saída para o console dos pais.
Vantagens do uso do shell para processos infantis.
Existem alguns benefícios de usar o shell executar. Você pode iniciar qualquer documento que tenha ações abertas registradas para seu tipo de arquivo. Por exemplo, você pode iniciar um documento de texto e um bloco de notas será aberto. Mas você deve lembrar que os fluxos de entrada / saída não serão redirecionados para o console dos pais dessa maneira.

Propriedade Process. StandardError.
A documentação de referência da API tem uma nova casa. Visite o navegador da API no docs. microsoft para ver a nova experiência.
Obtém um fluxo usado para ler a saída de erro do aplicativo.
Assembly: System (no System. dll)
Valor da propriedade.
Um StreamReader que pode ser usado para ler o fluxo de erros padrão do aplicativo.
O fluxo StandardError foi aberto para operações de leitura assíncronas com BeginErrorReadLine.
Quando um Processo grava texto em seu fluxo de erro padrão, esse texto normalmente é exibido no console. Ao redirecionar o fluxo StandardError, você pode manipular ou suprimir a saída de erro de um processo. Por exemplo, você pode filtrar o texto, formatá-lo de forma diferente ou escrever a saída para o console e um arquivo de log designado.
Para usar StandardError, você deve definir ProcessStartInfo. UseShellExecute como falso e você deve definir ProcessStartInfo. RedirectStandardError como verdadeiro. Caso contrário, a leitura do fluxo StandardError lança uma exceção.
O fluxo StandardError 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 de erro do processo. Essas operações de leitura síncrona não são concluídas até que o Processo associado escreva em seu fluxo StandardError ou encerre o fluxo.
Em contraste, BeginErrorReadLine inicia operações de leitura assíncronas no fluxo StandardError. Este método habilita um manipulador de eventos designado para a saída do fluxo e retorna imediatamente ao chamador, o 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 chamador a partir do fluxo StandardError e a escrita do processo filho a esse fluxo. Essas dependências podem resultar em condições de impasse. Quando o chamador lê do fluxo redirecionado de um processo filho, depende da criança. O chamador aguarda a operação de leitura até que a criança grava a transmissão ou encerre o fluxo. Quando o processo filho grava dados suficientes para preencher o fluxo redirecionado, ele depende do pai. O processo filho aguarda a próxima operação de gravação até que o pai lê do fluxo completo ou fecha o fluxo. A condição de deadlock resulta quando o processo do chamador e filho aguardam um para o outro para concluir uma operação, e nenhum deles pode prosseguir. Você pode evitar deadlocks avaliando as dependências entre o chamador eo processo filho.
O seguinte código C #, por exemplo, mostra como ler de um fluxo redirecionado e aguarde o processo filho sair.
O exemplo de código evita uma condição de bloqueio chamando p. StandardError. ReadToEnd antes de p. WaitForExit. Uma condição de impasse pode resultar se o processo pai chama p. WaitForExit antes de p. StandardError. ReadToEnd e o processo filho grava texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente o processo filho para sair. O processo filho esperaria indefinidamente para o pai ler do fluxo completo do StandardError.
Há um problema semelhante ao ler todo o texto da saída padrão e dos fluxos de erro padrão. O código C # a seguir, por exemplo, executa uma operação de leitura em ambos os fluxos.
O exemplo de código evita a condição de bloqueio executando operações de leitura assíncronas no fluxo StandardOutput. Um estado de impasse resulta se o processo pai chamar p. StandardOutput. ReadToEnd seguido de p. StandardError. ReadToEnd e o processo filho escreve texto suficiente para preencher o fluxo de erros. O processo pai aguardaria indefinidamente o processo filho para fechar o fluxo StandardOutput. O processo filho esperaria indefinidamente para o pai ler do fluxo completo do StandardError.
Você pode usar operações de leitura assíncronas para evitar essas dependências e seu potencial de impasse. Alternativamente, você pode evitar a condição de bloqueio criando dois tópicos e lendo a saída de cada fluxo em um segmento separado.
Você não pode misturar operações de leitura assíncronas e síncronas em um fluxo redirecionado. Uma vez que o fluxo redirecionado de um Processo é aberto em 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 BeginErrorReadLine com uma chamada para ReadLine no fluxo StandardError 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.
O exemplo a seguir usa o comando net use junto com um argumento fornecido pelo usuário para mapear um recurso de rede. Em seguida, lê o fluxo de erros padrão do comando net e o escreve para console.
para uma confiança total para o chamador imediato. Este membro não pode ser usado por código parcialmente confiável.

Comments