2009-02-01 11 views

Respuesta

8

Realmente no hay nada que puedas hacer si tu proceso es asesinado. Por definición, matar un proceso es solo eso, matarlo. El proceso no tiene la oportunidad de ejecutar ningún código. Esto es mucho "por diseño".

Imagine que puede registrar una rutina que se llamó cuando su proceso fue cancelado por el usuario (o por otro proceso). ¿Qué haría? Todos los otros hilos en su proceso estarían en un estado indeterminado. ¿Cómo se sincronizaría con ellos? Recuerde, la idea es que el proceso debe ser asesinado.

El otro escenario es aún más difícil: su código es benigno y trata de hacer lo correcto - p. limpiar y ser un buen ciudadano del sistema. Cierto código no lo es Imagínense qué gran beneficio para un autor de malware sería si el sistema operativo permitiera que el código se ejecutara en un proceso que estaba siendo destruido. Sería lo suficientemente malo para los procesos maliciosos que se ejecutaban con privilegios de usuario estándar, y completamente horrible para cualquier ejecución con privilegios administrativos.

La finalización crítica y el manejo de excepciones estructuradas no resolverán este problema fundamental.

EN la parte superior, el sistema operativo liberará todos los recursos que conoce cuando se mata el proceso, es decir, la memoria y objetos kernel. Esos no tendrán fugas. Pero el explorador no sabe acerca de su proceso, por lo que no puede solucionarlo.

Una forma de resolver esto sería tener un proceso de monitoreo que haga un seguimiento de sus otros procesos y lo limpie. Puede hacer esto con un proceso simple o con un servicio. También podría considerar algún tipo de extensión de shell que tuviera su propio hilo que hiciera lo mismo.

1

Teóricamente, los O/S deberían desasignar recursos después de que se mate el proceso. ¿En qué tipo de recursos estás pensando en particular?


Editar:

Ok, es un poco difícil de explicar. Estoy usando una biblioteca que está envolviendo algunas funciones del sistema operativo para administrar algunas extensiones de Shell. Cuando la aplicación se cierra sin llamar explícitamente a los métodos apropiados, todo el explorador se congela y necesito reiniciarlo.

Cualquier DLL no administrada se supone (según la documentación) invocada con un evento DLL_PROCESS_DETACH; sin embargo, este evento DLL_PROCESS_DETACH no se invoca cuando finaliza el proceso a través de la API TerminateProcess.

Google para these terms volvió a The Old New Thing : Why can't you trap TerminateProcess? que dice: "Una vez que matan con TerminateProcess, no más código en modo de usuario se ejecutará en ese proceso. Se ha ido."

Debido a todo lo que está tratando de el trabajo con (es decir, .NET, Explorer, Shell, COM) está sucediendo en modo de usuario, creo que la respuesta es que no hay forma de hacer lo que desea.

En su lugar, tal vez haya otra forma: por ejemplo, agregando código a las extensiones de su Shell para que se den cuenta si el proceso se abstuvo.

+0

Ok, es un poco difícil de explicar. Estoy usando una biblioteca que está envolviendo algunas funciones del sistema operativo para administrar algunas extensiones de Shell. Cuando la aplicación se cierra sin llamar explícitamente a los métodos apropiados, todo el explorador se congela y necesito reiniciarlo. – user57528

+0

DLL_PROCESS_DETACH no se pasa a DllMain cuando la terminación es causada por TerminateProcess. –

+0

Gracias Barry: Voy a editar mi respuesta en consecuencia. – ChrisW

0

Puede intentar envolver todo su proceso en una declaración try/finally (coloca la materia de desasignación en la cláusula finally), pero en algunos casos incluso eso no será suficiente.

En realidad, creo que podría iniciar un hilo de fondo de su proceso para hacer todas las cosas y Thread.Join() con su hilo principal para que si algo falla en el hilo secundario, el hilo principal todavía pueda para hacer las cosas bien. Por supuesto, esto no funcionará si todo el proceso finaliza por alguna razón.

También podría iniciar un proceso secundario y llamar a Process.WaitForExit(), pero no estoy seguro de si su cosa relacionada con el shell podría funcionar con un enfoque de procesos múltiples.

4

No hay forma de ejecutar código arbitrario al finalizar dentro de un proceso que está a punto de ser cancelado por una llamada al TerminateProcess, como por Administrador de tareas u otra utilidad de proceso como TSKILL o TASKKILL.

Ni los finalizadores críticos, ni los finalizadores ordinarios, ni los bloques try/finally, y ciertamente no los meros objetos que implementan IDisposable pueden hacer que el código se ejecute en este escenario. Incluso los eventos de separación de DLL no se invocarán desde una terminación de proceso a través del TerminateProcess.

Lo mejor que puede hacer es usar un proceso de vigilancia que supervisa el proceso original y ejecuta el código correspondiente cuando finaliza el proceso original.

Cuestiones relacionadas