6

当进程被任务管理器杀死时,我如何释放资源?有没有办法在进程关闭之前调用函数?

4

4 回答 4

8

如果你的进程被杀死,你真的无能为力。根据定义,杀死一个进程就是——杀死它。该进程没有机会运行任何代码。这是非常“设计”的。

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

另一种情况更难:你的代码是良性的,并且试图做正确的事情——例如清理并成为一个好的系统公民。有些代码不是。想象一下,如果操作系统允许为被杀死的进程运行代码,这对恶意软件作者来说将是多么大的福音。对于以标准用户权限运行的恶意进程来说,这已经够糟糕的了,而对于任何以管理权限运行的恶意进程来说都是非常糟糕的。

关键的最终确定和结构化的异常处理不会解决这个基本问题。

从好的方面来说,当你的进程被杀死时,操作系统将释放它所知道的所有资源,即内存和内核对象。那些不会泄漏。但是资源管理器不了解您的流程,因此无法对其进行清理。

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

于 2009-02-01T21:06:10.150 回答
4

在即将被调用终止的进程(TerminateProcess例如任务管理器)或其他进程实用程序(例如 TSKILL 或 TASKKILL)中,无法在终止时执行任意代码。

关键终结器,普通终结器,try/finally 块,当然不仅仅是实现的对象都不会IDisposable导致代码在这种情况下执行。即使是 DLL 分离事件也不会通过TerminateProcess.

您可以做的最好的事情是使用一个看门狗进程来监视您的原始进程并在原始进程终止时执行相关代码。

于 2009-02-01T21:26:04.930 回答
1

理论上,操作系统应该在进程被杀死后释放资源。您特别考虑哪种资源?


编辑:

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

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

谷歌搜索这些术语出现了旧的新事物:你为什么不能捕获 TerminateProcess? 上面写着,“一旦你用 TerminateProcess 终止,就不会再在该进程中运行用户模式代码了。它消失了。

因为您尝试使用的所有内容(即.NET、Explorer、Shell、COM)都是在用户模式下发生的,所以我认为答案是没有办法做您想做的事。

相反,也许还有另一种方法:例如,通过将代码添加到您的 Shell 扩展,以便它们知道您的进程是否异常。

于 2009-02-01T20:35:08.043 回答
0

您可以尝试将整个过程包装在 try/finally 语句中(您将释放的内容放在 finally 子句中),但在某些情况下,这还不够。

实际上,我认为你可以从你的进程中启动一个后台线程来做所有的事情,然后用你的主线程 Thread.Join() ,这样如果子线程出现问题,主线程仍然能够把事情做好. 当然,如果整个过程由于某种原因终止,这将不起作用。

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

于 2009-02-01T20:52:24.063 回答