c# - form - Desasignar recursos en la terminación del proceso
task kill c# (4)
¿Cómo puedo desasignar recursos cuando el proceso es asesinado, por ejemplo, por el Administrador de tareas? ¿Hay alguna manera de llamar a una función antes de que se cierre el proceso?
Podrías intentar envolver todo tu proceso en una declaración try / finally (pones la materia de desasignación en la cláusula finally), pero en algunos casos incluso eso no será suficiente.
De hecho, creo que podría iniciar un hilo de fondo de su proceso para hacer todo el trabajo y Thread.Join () con su hilo principal para que, si algo falla en el hilo secundario, el hilo principal aún pueda 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 hijo 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.
Teóricamente, el O / S debería desasignar los recursos después de que se mate el proceso. ¿En qué tipo de recursos estás pensando en particular?
Editar:
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.
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 llama cuando el proceso finaliza a través de la API TerminateProcess
.
Buscando en Google estos términos apareció The Old New Thing: ¿Por qué no puedes atrapar TerminateProcess? que dice: " Una vez que mata con TerminateProcess, no se ejecutará más código de modo de usuario en ese proceso. Se ha ido " .
Debido a que todo lo que está tratando de trabajar (es decir, .NET, Explorer, Shell, COM) está sucediendo en el modo de usuario, creo que la respuesta es que no hay forma de hacer lo que quiera.
En cambio, tal vez haya otra forma: por ejemplo, agregando código a las extensiones de su Shell para que se den cuenta si su proceso ha sido cancelado.
No hay forma de ejecutar código arbitrario al finalizar en un proceso que está a punto de ser cancelado por una llamada a TerminateProcess
, como por ejemplo 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 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 la terminación de un proceso a través de TerminateProcess
.
Lo mejor que puede hacer es usar un proceso de vigilancia que supervisa su proceso original y ejecuta el código relevante cuando finaliza el proceso original.
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 fue llamada cuando su proceso fue asesinado 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, por ejemplo, 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.
Por el lado positivo, el SO liberará todos los recursos que conoce cuando se mata su proceso, es decir, la memoria y los 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.