Question

Comment puis-je libérer des ressources lorsque le processus est tué par, par exemple, le gestionnaire de tâches? Est-il possible d'appeler une fonction avant la fermeture du processus?

Était-ce utile?

La solution

Vous ne pouvez vraiment rien faire si votre processus est tué. Par définition, tuer un processus n’est que cela: le tuer. Le processus n'a pas la possibilité d'exécuter du code. C’est très bien & «De par la conception &»;

Imaginez que vous puissiez enregistrer une routine appelée lorsque votre processus a été tué par l'utilisateur (ou par un autre processus). Que ferait-il? Tous les autres threads de votre processus seraient dans un état indéterminé. Comment synchroniseriez-vous avec eux? Rappelez-vous, l’idée est que le processus doit être éliminé.

L’autre scénario est encore plus compliqué: votre code est inoffensif et tente de faire ce qu’il faut - par exemple. nettoyer et être un bon citoyen du système. Certains codes ne sont pas. Imaginez quel avantage pour un auteur de programme malveillant ce serait si le système d'exploitation permettait à du code d'être exécuté pour un processus en cours de suppression. Ce serait assez grave pour les processus malveillants qui s'exécutaient avec des privilèges d'utilisateur standard et complètement affreux pour toute exécution avec des privilèges d'administrateur.

La finalisation critique et la gestion structurée des exceptions ne résoudront pas ce problème fondamental.

A l’avantage, le système d’exploitation libérera toutes les ressources qu’il sait sur le moment où votre processus est tué, à savoir la mémoire et les objets du noyau. Ceux qui ne vont pas fuir. Mais explorer ne connaît pas votre processus, il ne peut donc pas le nettoyer.

Un moyen de résoudre ce problème consiste à mettre en place un processus de surveillance qui assure le suivi de l’état de vos autres processus et le nettoie. Vous pouvez le faire avec un processus simple ou avec un service. Vous pouvez également envisager une sorte d’extension de shell qui a son propre thread qui fait la même chose.

Autres conseils

Il n’existe aucun moyen d’exécuter du code arbitraire lors de la terminaison dans un processus sur le point d’être tué par un appel à TerminateProcess, tel que par le Gestionnaire des tâches, ou par un autre utilitaire de processus tel que TSKILL ou TASKKILL.

Ni les finaliseurs critiques, ni les finaliseurs ordinaires, ni les blocs try / finally, et certainement pas de simples objets qui implémentent IDisposable ne peuvent provoquer l'exécution de code dans ce scénario. Même les événements de détachement de DLL ne seront pas appelés à la fin d'un processus via <=>.

Le mieux que vous puissiez faire est d'utiliser un processus de surveillance qui surveille votre processus d'origine et exécute le code pertinent lorsque le processus d'origine est terminé.

Théoriquement, le système d’exploitation devrait désallouer les ressources une fois le processus tué. À quel type de ressource pensez-vous en particulier?

Modifier:

  

Ok, c'est un peu difficile à expliquer. J'utilise une bibliothèque qui encapsule certaines fonctions du système d'exploitation pour gérer certaines extensions Shell. Lorsque l'application se ferme sans appeler explicitement les méthodes appropriées, tout l'explorateur se bloque et je dois le redémarrer.

Toute DLL non gérée est (selon la documentation) supposée être invoquée avec un événement DLL_PROCESS_DETACH; cependant, cet événement TerminateProcess n'est pas appelé lorsque le processus est arrêté via l'API <=>.

.

Recherchez Google pour ces termes ont été renvoyés Ancienne nouvelle chose: pourquoi ne pouvez-vous pas piéger TerminateProcess? qui dit & "; une fois que vous aurez tué avec TerminateProcess, plus aucun code en mode utilisateur ne sera exécuté dans ce processus. C'est parti. & ";

Parce que tout ce que vous essayez de travailler (à savoir .NET, Explorer, Shell, COM) se passe en mode utilisateur, je pense que la réponse est qu'il n'y a aucun moyen de faire ce que vous voulez.

Au lieu de cela, il existe peut-être un autre moyen: par exemple, en ajoutant du code à vos extensions Shell afin qu'elles se rendent compte si votre processus est interrompu.

Vous pouvez essayer de résumer tout votre processus dans une instruction try / finally (vous mettez le contenu de la désaffectation dans la clause finally), mais dans certains cas, cela ne suffira pas.

En fait, je pense que vous pourriez lancer un thread d'arrière-plan à partir de votre processus pour effectuer tout le travail et Thread.Join () avec votre thread principal. Ainsi, en cas de problème, le thread principal sera toujours en mesure de faire les choses bien. Bien entendu, cela ne fonctionnera pas si l'ensemble du processus est arrêté pour une raison quelconque.

Vous pouvez également lancer un processus enfant et appeler Process.WaitForExit () mais je ne suis pas sûr que votre solution liée au shell puisse fonctionner avec une approche multi-processus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top