2009-02-01 6 views

Répondre

8

Il n'y a vraiment rien que vous puissiez faire si votre processus est tué. Par définition, tuer un processus, c'est le tuer. Le processus n'a pas l'occasion d'exécuter du code. C'est très "par conception". Imaginez que vous puissiez enregistrer une routine qui a été 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 vous synchroniseriez-vous avec eux? Rappelez-vous, l'idée est que le processus doit être tué.

L'autre scénario est encore plus difficile: votre code est inoffensif et essaie de faire ce qui est juste - p. nettoyer et être un bon citoyen du système. Un code n'est pas. Imaginez ce que serait un avantage pour un auteur de logiciels malveillants si le système d'exploitation permettait l'exécution de code pour un processus en cours de suppression. Il serait assez mauvais pour les processus malveillants qui fonctionnaient avec des privilèges d'utilisateur standard, et complètement horrible pour toute exécution avec des privilèges administratifs.

La finalisation critique et la gestion des exceptions structurées ne résoudront pas ce problème fondamental. A l'inverse, le système d'exploitation libèrera toutes les ressources qu'il connaît au moment de la destruction de votre processus, à savoir les objets de la mémoire et du noyau. Ceux-ci ne fuiront pas. Mais l'explorateur ne connaît pas votre processus, donc il ne peut pas le nettoyer. Une façon de résoudre ce problème serait d'avoir 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 pourriez également envisager une sorte d'extension de shell qui a son propre thread qui a fait la même chose.

1

Théoriquement, l'O/S devrait libérer des ressources après la fin du processus. À quel type de ressource pensez-vous en particulier?


Edit:

Ok, il est un peu difficile à expliquer. J'utilise une bibliothèque qui encapsule certaines fonctions du système d'exploitation pour gérer certaines extensions du 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é est (selon la documentation) censée être invoquée avec un événement DLL_PROCESS_DETACH; toutefois, cet événement DLL_PROCESS_DETACH n'est pas appelé lorsque le processus est arrêté via l'API TerminateProcess.

recherche sur Google pour these terms tournées vers le haut The Old New Thing : Why can't you trap TerminateProcess? qui dit, « Une fois que vous tuez avec TerminateProcess, pas plus de code en mode utilisateur se déroulera dans ce processus. Il est parti. »

Parce que tout ce que vous essayez de travailler avec (par exemple .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 obsolète.

+0

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 du 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. – user57528

+0

DLL_PROCESS_DETACH n'est pas passé à DllMain lorsque la terminaison est provoquée par TerminateProcess. –

+0

Merci Barry: Je vais modifier ma réponse en conséquence. – ChrisW

0

Vous pouvez essayer d'encapsuler l'ensemble de votre processus dans une instruction try/finally (vous mettez les clauses de désallocation dans la clause finally), mais dans certains cas, même cela ne suffira pas.

En fait, je pense que vous pouvez lancer un thread d'arrière-plan de votre processus pour faire toutes les choses et Thread.Join() avec votre thread principal afin que si quelque chose ne va pas dans le thread fils, le thread principal pour bien faire les choses. Bien sûr, cela ne fonctionnera pas si tout le processus se termine pour une raison quelconque.

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

4

Il n'existe aucun moyen d'exécuter du code arbitraire à la fin d'un processus sur le point d'être interrompu par un appel à TerminateProcess, comme par le Gestionnaire des tâches ou un autre utilitaire de traitement tel que TSKILL ou TASKKILL.

Ni les finaliseurs critiques, ni les finaliseurs ordinaires, ni les blocs try/finally, et certainement pas les simples objets qui implémentent IDisposable peuvent provoquer l'exécution de code dans ce scénario. Même les événements de détachement DLL ne seront pas invoqués à partir d'une terminaison de processus via TerminateProcess. Le mieux que vous pouvez faire est d'utiliser un processus de surveillance qui surveille votre processus d'origine et exécute le code approprié lorsque le processus d'origine est terminé.

Questions connexes