Вопрос

Как я могу освободить ресурсы, когда процесс завершается, например, диспетчером задач?Есть ли способ вызвать функцию до закрытия процесса?

Это было полезно?

Решение

На самом деле вы ничего не сможете сделать, если ваш процесс будет убит.По определению, убийство процесса — это просто его убийство.Процесс не получает возможности запускать какой-либо код.Это во многом «по замыслу».

Представьте себе, что вы можете зарегистрировать процедуру, которая вызывалась, когда ваш процесс был завершен пользователем (или другим процессом).Что бы это сделало?Все остальные потоки вашего процесса будут в неопределенном состоянии. Как бы вы с ними синхронизировались?Помните, идея в том, что процесс нужно убить.

Другой сценарий еще сложнее:ваш код безвреден и пытается поступить правильно - например.наведите порядок и будьте хорошим гражданином системы.Некоторый код нет.Представьте себе, каким благом было бы для автора вредоносного ПО, если бы операционная система позволяла запускать код для уничтожаемого процесса.Это было бы достаточно плохо для вредоносных процессов, запущенных с правами обычного пользователя, и совершенно ужасно для любых, запущенных с правами администратора.

Критическая финализация и структурированная обработка исключений не решат эту фундаментальную проблему.

С другой стороны, ОС освободит все ресурсы, о которых она знает, когда ваш процесс будет завершен, а именно память и объекты ядра.Они не будут протекать.Но проводник не знает о вашем процессе, поэтому не может его очистить.

Одним из способов решения этой проблемы является создание процесса мониторинга, который отслеживает состояние других ваших процессов и очищает его.Вы можете сделать это с помощью простого процесса или службы.Вы также можете подумать о каком-то расширении оболочки, имеющем собственный поток, который делает то же самое.

Другие советы

Невозможно выполнить произвольный код после завершения внутри процесса, который вот-вот будет завершен вызовом TerminateProcess, например, с помощью диспетчера задач или другой утилиты процесса, например TSKILL или TASKKILL.

Ни критические финализаторы, ни обычные финализаторы, ни блоки try/finally, и уж точно не просто объекты, реализующие IDisposable может привести к выполнению кода в этом сценарии.Даже события отсоединения DLL не будут вызываться при завершении процесса через TerminateProcess.

Лучшее, что вы можете сделать, — это использовать сторожевой процесс, который контролирует исходный процесс и выполняет соответствующий код, когда исходный процесс завершается.

Теоретически операционная система должна освободить ресурсы после завершения процесса.О каком конкретно ресурсе вы думаете?


Редактировать:

Хорошо, это довольно сложно объяснить.Я использую библиотеку, которая объединяет некоторые функции ОС для управления некоторыми расширениями оболочки.Когда приложение закрывается без явного вызова соответствующих методов, весь проводник зависает, и мне нужно его перезапустить.

Любая неуправляемая DLL (согласно документации) должна вызываться с помощью DLL_PROCESS_DETACH событие;однако, это DLL_PROCESS_DETACH событие не вызывается, когда процесс завершается через TerminateProcess API.

Поиск в Google эти условия появился Старая новая вещь:Почему вы не можете перехватить TerminateProcess?который говорит: "После того, как вы завершите процесс с помощью TerminateProcess, в этом процессе больше не будет выполняться код пользовательского режима.Оно ушло."

Потому что все, с чем вы пытаетесь работать (т..NET, Explorer, Shell, COM) происходит в пользовательском режиме, я думаю, ответ заключается в том, что нет возможности делать то, что вы хотите.

Вместо этого, возможно, есть другой способ:например, добавив код в ваши расширения Shell, чтобы они понимали, что ваш процесс нарушен.

Вы можете попробовать обернуть весь процесс в оператор try/finally (вы помещаете данные об освобождении в предложениеfinally), но в некоторых случаях даже этого будет недостаточно.

На самом деле, я думаю, вы могли бы запустить фоновый поток из своего процесса, чтобы выполнить все действия, и Thread.Join() с вашим основным потоком, чтобы, если что-то пойдет не так в дочернем потоке, основной поток все равно сможет все сделать правильно. .Конечно, это не сработает, если по какой-то причине весь процесс завершится.

Вы также можете запустить дочерний процесс и вызвать Process.WaitForExit(), но я не уверен, что ваша вещь, связанная с оболочкой, может работать с многопроцессным подходом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top