简体   繁体   English

在流程终止时释放资源

[英]Deallocate resources on process termination

How I can deallocate resources when the process gets killed by, for example, the Task Manager? 当进程被例如任务管理器杀死时,如何释放资源? Is there a way to call a function before the process gets closed? 有没有办法在进程关闭之前调用函数?

There really is nothing you can do if your process is killed. 如果你的进程被杀,你真的无能为力。 By definition, killing a process is just that - killing it. 根据定义,杀死一个进程只是 - 杀死它。 The process does not get an opportunity to run any code. 该过程没有机会运行任何代码。 This is very much "by design". 这非常“按设计”。

Imagine that you could register a routine that was called when your process was killed by the user (or by another process). 想象一下,您可以注册在您的进程被用户(或其他进程)杀死时调用的例程。 What would it do? 它会做什么? All the other threads in your process would be in an indeterminate state, How would you synchronize with them? 您流程中的所有其他线程都处于不确定状态,您将如何与它们同步? Remember, the idea is that the process needs to be killed. 请记住,这个想法是需要杀死这个过程。

The other scenario is even tougher: your code is benign and trying to do the right thing - eg clean up and be a good system citizen. 另一种情况甚至更加困难:你的代码是良性的,并且正在努力做正确的事情 - 例如清理并成为一名优秀的系统公民。 Some code isn't. 有些代码不是。 Imagine what a boon to a malware author it would be if the OS allowed code to be run for a process that was being killed. 想象一下,如果操作系统允许为正在被杀死的进程运行代码,那将对恶意软件作者带来什么好处。 It would be bad enough for malicious processes that were running with standard user privileges, and completely awful for any running with administrative privileges. 对于使用标准用户权限运行的恶意进程而言,这对于任何具有管理权限的运行来说都是非常糟糕的。

Critical finalizes and structured exception handling will not solve this fundamental issue. 关键的最终结构和结构化异常处理不能解决这个基本问题。

ON the upside, the OS will free all the resources it knows about when your process is killed, namely memory and kernel objects. 从好的方面来说,操作系统将释放它在进程被终止时所知道的所有资源,即内存和内核对象。 Those will not leak. 那些不会泄漏。 But explorer doesn't know about your process so it cannot clean up for it. 但是资源管理器并不了解您的流程,因此无法清理它。

One way to solve this would be to have a monitoring process that keeps track of your other processes state and cleans up for it. 解决此问题的一种方法是建立一个监控流程来跟踪您的其他流程状态并清理它。 You could do this with a simple process, or with a service. 您可以通过简单的流程或服务来完成此操作。 You might also consider some kind of shell extension that had its own thread that did the same thing. 你也可以考虑某种shell扩展,它有自己的线程做同样的事情。

There is no way to execute arbitrary code upon termination within a process which is about to be killed by a call to TerminateProcess , such as by Task Manager, or another process utility such as TSKILL or TASKKILL. 在通过调用TerminateProcess (例如通过任务管理器或其他流程实用程序,如TSKILL或TASKKILL)即将终止的进程中终止时,无法执行任意代码。

Neither critical finalizers, nor ordinary finalizers, nor try/finally blocks, and certainly not mere objects which implement IDisposable can cause code to be executed in this scenario. 既不是关键的终结器,也不是普通的终结器,也不是try / finally块,当然也不仅仅是实现IDisposable对象可能导致在这种情况下执行代码。 Even DLL detach events will not be invoked from a process termination via TerminateProcess . 甚至DLL分离事件也不会通过TerminateProcess从进程终止中调用。

The best you can do is to use a watchdog process which monitors your original process and executes relevant code when the original process is terminated. 您可以做的最好的事情是使用监视程序进程监视原始进程并在原始进程终止时执行相关代码。

Theoretically the O/S should deallocate resources after the process is killed. 从理论上讲,O / S应该在进程被杀死后释放资源。 What kind of resource are you thinking of in particular? 你特别想到什么样的资源?


Edit: 编辑:

Ok, it's kinda tricky to explain. 好的,解释起来有点棘手。 I'm using a library that is wrapping some OS functions to manage some Shell Extensions. 我正在使用一个包含一些OS函数的库来管理一些Shell Extensions。 When the application closes without calling explicitly the appropriate methods, all explorer freezes and I need to restart it. 当应用程序关闭但没有明确调用适当的方法时,所有资源管理器都会冻结,我需要重新启动它。

Any unmanaged DLL is (according to the documentation) supposed to be invoked with a DLL_PROCESS_DETACH event; 应该使用DLL_PROCESS_DETACH事件调用任何非托管DLL(根据文档); however, this DLL_PROCESS_DETACH event isn't called when the process is terminated via the TerminateProcess API. 但是,当通过TerminateProcess API终止进程时,不会调用此DLL_PROCESS_DETACH事件。

Googling for these terms turned up The Old New Thing : Why can't you trap TerminateProcess? 谷歌搜索这些术语出现旧的新事物:为什么你不能陷阱TerminateProcess? which says, " Once you kill with TerminateProcess, no more user-mode code will run in that process. It's gone. " 其中说:“ 一旦你杀了TerminateProcess,就不会再有用户模式的代码在那个过程中运行。它已经消失了。

Because everything you're trying to work with (ie .NET, Explorer, Shell, COM) is happening in user-mode, I think the answer is that there's no way to do what you want. 因为您尝试使用的所有内容(即.NET,Explorer,Shell,COM)都是在用户模式下进行的,所以我认为答案是没有办法做你想做的事情。

Instead, perhaps there's another way: for example, by adding code to your Shell extensions so that they realize if your process is abended. 相反,也许还有另一种方法:例如,通过向Shell扩展添加代码,以便他们意识到您的流程是否被废弃。

You could try wrapping your whole process in a try/finally statement (you put the deallocation stuff in the finally clause), but in some cases even that will not be enough. 您可以尝试将整个过程包装在try / finally语句中(将释放内容放在finally子句中),但在某些情况下即使这样也是不够的。

Actually, I think you could launch a background thread from your process to do all the stuff and Thread.Join() with your main thread so that if something goes wrong in the child thread, the main thread will be still able to get things right. 实际上,我认为你可以从你的进程中启动一个后台线程,用你的主线程做所有的东西和Thread.Join(),这样如果在子线程中出现问题,主线程仍然能够把事情弄清楚。 Of course, this will not work if the whole process gets terminated for some reason. 当然,如果由于某种原因整个过程终止,这将不起作用。

You could also launch a child process and call Process.WaitForExit() but I'm not sure if your shell-related thing could work with a multi-process approach. 你也可以启动一个子进程并调用Process.WaitForExit(),但我不确定你的shell相关的东西是否可以使用多进程方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM