Pregunta

¿Cómo puedo desasignar recursos cuando, por ejemplo, el Administrador de tareas mata el proceso? ¿Hay alguna forma de llamar a una función antes de que se cierre el proceso?

¿Fue útil?

Solución

Realmente no hay nada que pueda hacer si su proceso se anula. 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 & Quot; por diseño & Quot ;.

Imagine que puede registrar una rutina que se llamó cuando el proceso fue cancelado por el usuario (o por otro proceso). ¿Qué haría eso? 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 necesita ser eliminado.

El otro escenario es aún más difícil: su código es benigno e intenta hacer lo correcto, p. limpiar y ser un buen ciudadano del sistema. Algún código no lo es. Imagine lo que sería una bendición para un autor de malware si el sistema operativo permitiera ejecutar el código para un proceso que se estaba eliminando. Sería suficientemente malo para procesos maliciosos que se ejecutaban con privilegios de usuario estándar, y completamente horrible para cualquier ejecución con privilegios administrativos.

Las finalizaciones críticas y el manejo estructurado de excepciones no resolverán este problema fundamental.

Por el lado positivo, el sistema operativo liberará todos los recursos que conoce cuando se finaliza su proceso, es decir, objetos de memoria y kernel. Esos no se filtrarán. Pero el explorador no conoce su proceso, por lo que no puede limpiarlo.

Una forma de resolver esto sería tener un proceso de monitoreo que realice un seguimiento del estado 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.

Otros consejos

No hay forma de ejecutar código arbitrario al finalizar dentro de un proceso que está a punto de ser cancelado por una llamada a TerminateProcess, como por el 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 son simples 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 la finalización del proceso a través de <=>.

Lo mejor que puede hacer es utilizar un proceso de vigilancia que supervise su proceso original y ejecute el código relevante cuando finalice el proceso original.

Teóricamente, el O / S debe desasignar recursos después de que el proceso finalice. ¿En qué tipo de recurso está pensando en particular?


Edición :

  

Ok, es un poco complicado 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.

Se supone que cualquier DLL no administrado (de acuerdo con la documentación) debe invocarse con un evento DLL_PROCESS_DETACH; sin embargo, este evento TerminateProcess no se llama cuando el proceso finaliza a través de la API <=>.

Google para estos términos aparecieron The Old New Thing: ¿Por qué no puede atrapar TerminateProcess? que dice, " Una vez que matas con TerminateProcess, no se ejecutará más código de modo de usuario en ese proceso. Se ha ido. & Quot;

Debido a que todo con lo que está tratando de trabajar (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 quiere.

En cambio, tal vez haya otra forma: por ejemplo, agregando código a sus extensiones de Shell para que se den cuenta si su proceso está suspendido.

Podrías intentar envolver todo tu proceso en una declaración try / finally (pones las cosas de desasignación en la cláusula finalmente), 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 sale mal en el hilo secundario, el hilo principal aún podrá hacer las cosas bien Por supuesto, esto no funcionará si todo el proceso se termina por alguna razón.

También puede 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 multiproceso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top