Pergunta

Como posso negociar recursos quando o processo é morto por, por exemplo, o gerente de tarefas? Existe uma maneira de chamar uma função antes que o processo seja fechado?

Foi útil?

Solução

Realmente não há nada que você possa fazer se o seu processo for morto. Por definição, matar um processo é exatamente isso - matando -o. O processo não tem a oportunidade de executar nenhum código. Isso é muito "por design".

Imagine que você pode registrar uma rotina chamada quando seu processo foi morto pelo usuário (ou por outro processo). O que faria? Todos os outros threads do seu processo estariam em um estado indeterminado, como você sincronizaria com eles? Lembre -se, a idéia é que o processo precise ser morto.

O outro cenário é ainda mais difícil: seu código é benigno e tentando fazer a coisa certa - por exemplo, limpe e ser um bom cidadão do sistema. Algum código não é. Imagine que benefício para um autor de malware seria se o sistema operacional permitisse que o código fosse executado para um processo que estava sendo morto. Seria ruim o suficiente para processos maliciosos que estavam sendo executados com privilégios de usuário padrão e completamente horríveis para qualquer execução com privilégios administrativos.

A crítica finaliza e o manuseio de exceção estruturado não resolverá essa questão fundamental.

No lado positivo, o sistema operacional libertará todos os recursos que conhece quando seu processo é morto, a saber, os objetos de memória e kernel. Aqueles não vazam. Mas o Explorer não sabe sobre o seu processo, portanto não pode limpar para ele.

Uma maneira de resolver isso seria ter um processo de monitoramento que acompanha o estado de seus outros processos e a limpeza. Você pode fazer isso com um processo simples ou com um serviço. Você também pode considerar algum tipo de extensão de concha que tinha seu próprio tópico que fazia a mesma coisa.

Outras dicas

Não há como executar o código arbitrário após a rescisão dentro de um processo que está prestes a ser morto por uma chamada para TerminateProcess, como o gerenciador de tarefas ou outro utilitário de processo, como TSKill ou TaskKill.

Nem finalizadores críticos, nem finalizadores comuns, nem tentam/finalmente bloqueiam, e certamente não meros objetos que implementam IDisposable pode fazer com que o código seja executado nesse cenário. Mesmo os eventos de destacamento de DLL não serão invocados a partir de uma terminação de processo via TerminateProcess.

O melhor que você pode fazer é usar um processo de Watchdog que monitora seu processo original e execute código relevante quando o processo original for encerrado.

Teoricamente, os O/S devem negociar recursos após a morte do processo. Em que tipo de recurso você está pensando em particular?


Editar:

Ok, é meio complicado de explicar. Estou usando uma biblioteca que está envolvendo algumas funções do sistema operacional para gerenciar algumas extensões de shell. Quando o aplicativo se fecha sem chamar explicitamente os métodos apropriados, todos o Explorer congela e eu preciso reiniciá -lo.

Qualquer DLL não gerenciada é (de acordo com a documentação) que deveria ser invocada com um DLL_PROCESS_DETACH evento; No entanto, isso DLL_PROCESS_DETACH o evento não é chamado quando o processo é encerrado através do TerminateProcess API.

Pesquisando no Google Estes termos apareceu A velha coisa: por que você não pode prender o TermineProcess?o que diz, "Depois de matar com o TermineProcess, nenhum código no modo de usuário será executado nesse processo. Foi-se."

Como tudo o que você está tentando trabalhar (ou seja .NET, Explorer, Shell, Com) está acontecendo no modo de usuário, acho que a resposta é que não há como fazer o que você deseja.

Em vez disso, talvez haja outra maneira: por exemplo, adicionando código às suas extensões de shell, para que elas percebam se o seu processo estiver encerrado.

Você pode tentar envolver todo o seu processo em uma declaração de tentativa/finalmente (você coloca o material de desalocação na cláusula finalmente), mas em alguns casos, mesmo isso não será suficiente.

Na verdade, acho que você poderia lançar um tópico de fundo do seu processo para fazer todas as coisas e thread.Join () com seu tópico principal para que, se algo der errado no tópico infantil, o tópico principal ainda poderá acertar as coisas . Obviamente, isso não funcionará se todo o processo for encerrado por algum motivo.

Você também pode lançar um processo infantil e chamado de processo.waitforexit (), mas não tenho certeza se sua coisa relacionada à shell poderia funcionar com uma abordagem com vários processos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top