当进程被任务管理器杀死时,如何解除资源释放?有没有办法在进程关闭之前调用函数?
答案 0 :(得分:8)
如果你的进程被杀,你真的无能为力。根据定义,杀死一个进程只是 - 杀死它。该过程没有机会运行任何代码。这非常“按设计”。
想象一下,您可以注册在您的进程被用户(或其他进程)杀死时调用的例程。它会做什么?您流程中的所有其他线程都处于不确定状态,您将如何与它们同步?请记住,这个想法是需要杀死这个过程。
另一种情况甚至更难:你的代码是良性的,并试图做正确的事情 - 例如清理并成为一个好的系统公民。有些代码不是。想象一下,如果操作系统允许为正在被杀死的进程运行代码,那将对恶意软件作者带来什么好处。对于使用标准用户权限运行的恶意进程而言,这对于任何具有管理权限的运行都是非常糟糕的。
关键的最终结构和结构化异常处理无法解决这个基本问题。
从好的方面来说,操作系统将释放它在进程被终止时所知道的所有资源,即内存和内核对象。那些不会泄漏。但是资源管理器并不了解您的流程,因此无法清理它。
解决此问题的一种方法是建立一个监控流程来跟踪您的其他流程状态并清理它。您可以通过简单的流程或服务来完成此操作。你也可以考虑某种shell扩展,它有自己的线程做同样的事情。
答案 1 :(得分:4)
在一个即将被调用TerminateProcess
的进程中终止时,无法执行任意代码,例如通过任务管理器或其他进程实用程序(如TSKILL或TASKKILL)。
关键终结器,普通终结器,try / finally块,当然不仅仅是实现IDisposable
的对象都可能导致在这种情况下执行代码。甚至DLL分离事件也不会通过TerminateProcess
从进程终止中调用。
您可以做的最好的事情是使用监视程序进程监视原始进程并在原始进程终止时执行相关代码。
答案 2 :(得分:1)
理论上,O / S应该在进程被杀死后释放资源。你特别想到什么样的资源?
修改强>
好的,解释起来有点棘手。我正在使用一个包含一些OS函数的库来管理一些Shell Extensions。当应用程序关闭而没有明确调用适当的方法时,所有资源管理器都会冻结,我需要重新启动它。
任何非托管DLL(根据文档)应该使用DLL_PROCESS_DETACH
事件调用;但是,当通过DLL_PROCESS_DETACH
API终止进程时,不会调用此TerminateProcess
事件。
Google these terms的Google搜索The Old New Thing : Why can't you trap TerminateProcess? 其中说,“一旦你终止了TerminateProcess,就不会再有用户模式代码在这个过程中运行了。它已经消失了。”
因为您尝试使用的所有内容(即.NET,Explorer,Shell,COM)都是在用户模式下进行的,所以我认为答案是没有办法做你想做的事。
相反,也许还有另一种方法:例如,通过向Shell扩展添加代码,以便他们意识到您的流程是否被废弃。
答案 3 :(得分:0)
您可以尝试将整个过程包装在try / finally语句中(将释放内容放在finally子句中),但在某些情况下即使这样也是不够的。
实际上,我认为你可以从你的进程启动一个后台线程,用你的主线程做所有的东西和Thread.Join(),这样如果在子线程中出现问题,主线程仍然可以搞好事。当然,如果由于某种原因终止整个过程,这将不起作用。
你也可以启动一个子进程并调用Process.WaitForExit()但是我不确定你的shell相关的东西是否可以用多进程方法。