2009-02-01 85 views
6

当进程被例如任务管理器终止时,我怎样才能释放资源?有没有办法在进程关闭之前调用函数?在进程终止时释放资源

+0

我回复了你的评论,编辑我的答案 – ChrisW 2009-02-01 20:54:21

回答

8

如果您的流程被杀死,那么您确实无能为力。根据定义,杀死一个进程就是这样 - 杀死它。该过程没有得到运行任何代码的机会。这非常“通过设计”。

想象一下,您可以注册一个在用户(或另一个进程)终止进程时调用的例程。它会做什么?你的进程中的所有其他线程将处于不确定状态,你将如何与它们同步?请记住,这个想法是,这个过程需要被杀死。

另一种情况更加严峻:你的代码是良性的,并试图做正确的事情 - 例如,清理并成为一名优秀的系统公民。有些代码不是。想象一下,如果操作系统允许代码针对正在被杀死的进程运行,那么对于恶意软件作者来说它是一个好处。对于使用标准用户权限运行的恶意进程来说,这将会很糟糕,并且对于任何使用管理权限运行的进程都是完全可怕的。

关键定稿和结构化异常处理并不能解决这个根本问题。

好处在于,操作系统将释放它知道的有关进程死亡的所有资源,即内存和内核对象。那些不会泄漏。但是,浏览器不知道你的过程,所以它不能清理它。

解决这个问题的一种方法是创建一个监视进程,以跟踪其他进程的状态并清理它。你可以用一个简单的过程或者一个服务来做到这一点。你也可以考虑某种外壳扩展,它有自己的线程来做同样的事情。

1

从理论上讲,O/S应该在进程终止后释放资源。你特别想到什么样的资源?


编辑:

好吧,它有点棘手的解释。我正在使用一个封装了一些OS功能的库来管理一些Shell扩展。当应用程序关闭而不显式调用适当的方法时,所有资源管理器都会冻结,我需要重新启动它。

任何非托管DLL(根据文档)应该被调用DLL_PROCESS_DETACH事件;但是,当通过TerminateProcess API终止进程时,不会调用此DLL_PROCESS_DETACH事件。

谷歌搜索these terms止跌回升The Old New Thing : Why can't you trap TerminateProcess? 它说,“一旦你用了TerminateProcess杀死,没有更多的用户模式代码都会在这个进程中运行。它不见了。

因为一切你想在用户模式下工作(即.NET,Explorer,Shell,COM),我认为答案是没有办法做到你想做的事。

相反,也许还有另外一种方法:例如,通过向Shell扩展添加代码,以便他们意识到您的进程是否被取消。

+0

好吧,这是一个棘手的解释。我正在使用一个封装了一些OS功能的库来管理一些Shell扩展。当应用程序关闭而不显式调用适当的方法时,所有资源管理器都会冻结,我需要重新启动它。 – user57528 2009-02-01 20:40:09

0

你可以尝试在try/finally语句中包装你的整个过程(你把释放的东西放在finally子句中),但是在某些情况下甚至是不够的。实际上,我认为你可以从你的进程中启动一个后台线程来完成所有的东西和Thread.Join()与你的主线程,这样如果在子线程中出现问题,主线程仍然能够把事情做好。当然,如果整个过程由于某种原因而终止,这将不起作用。

您也可以启动子进程并调用Process.WaitForExit(),但我不确定您的与shell相关的东西是否可以使用多进程方法。

4

在任务即将终止的过程中,如果任务管理器或其他过程实用程序(例如TSKILL或TASKKILL)致电TerminateProcess,则无法执行任意代码。

既不是关键的终结器,也不是普通的终结器,也不是尝试/终止块,当然也不是仅仅实现IDisposable的对象可能导致代码在这种情况下被执行。即使DLL分离事件也不会通过TerminateProcess从进程终止中调用。

您可以做的最好的方法是使用监视程序进程,该进程监视您的原始进程并在原始进程终止时执行相关代码。