.NET code在正常的进程退出执行?进程、正常、NET、code

2023-09-04 00:43:47 作者:动作假i

C 还有就是 atexit对功能,

里的AtExit()函数注册给定函数的调用,在正常的进程终止,或者通过出口(3),或通过从返回程序主()。

The atexit() function registers the given function to be called at normal process termination, either via exit(3) or via return from the program's main().

Python中也有类似的功能。

Python has a similar capability.

难道.NET提供了一种方法来调用code正常进程终止?我知道有像 DomainUnload ProcessExit ,但至少据我所知,这些都是不可靠的一些事情 - 无论是要求应用程序是一个Windows窗体(或WPF应用程序),或别的东西。我写$ C $下一个.dll,所以我不能靠像哉与主程序功能 - 包装在一个try / catch

Does .NET provide a way to call code at normal process termination? I know there are certain things like DomainUnload and ProcessExit, but at least as far as I can tell, these are unreliable - either requiring the application to be a Windows Forms (or WPF app), or something else. I am writing code for a .dll, so I can't rely on things like mucking with the main program function - wrapping it in a try/catch.

我的最终目标是执行一些文件清理(即刷新缓冲区并关闭)。如果我可以调用一些非托管code,例如一个WIN32API钩或什么的,我完全没有这一点。

My ultimate goal is to perform some file cleanup (i.e. flush buffers and close). If I can call some unmanaged code, e.g. a win32api hook or something, I'm perfectly fine with that.

推荐答案

有没有直接的答案,我知道的。

There is no straight-forward answer that I know of.

如果你想编写一个健壮的DLL,你应该prepare的几种情形:

If you want to write a robust DLL, you should prepare for several scenarios:

您$​​ C $ C托管在一个.NET应用程序,在默认的AppDomain。 (琐碎的情况下) 您$​​ C $ C托管在一个.NET应用程序,通过主机的code创建一个AppDomain。 您$​​ C $ C托管在非托管应用程序(它承载的CLR)。

第三方案是最难处理的,因为CLR可以通过宿主被禁止,因此管理code将不再执行。

The 3rd scenario is the hardest to deal with, since the CLR can be disabled by its host, so managed code won't execute anymore.

System.Windows.Forms.Application.ApplicationExit 是没有好处,因为它仅适用于WinForm的应用程序。

System.Windows.Forms.Application.ApplicationExit is no good since it only applies to WinForm applications.

System.AppDomain.DomainUnload 本身是没有好处,因为这是从来没有提出默认的AppDomain。

System.AppDomain.DomainUnload by itself is no good since it is never raised for the default AppDomain.

AppDomain.ProcessExit 本身是没有好:如果你的code托管在一个单独的AppDomain中,主机可能会卸载该应用程序域,因此该事件将永远提高。

AppDomain.ProcessExit by itself is no good: if your code is hosted in a separate AppDomain, the host might unload that AppDomain, so the event will never raise.

我试图掩盖大多数情况下,使用类似启动:

I'd start by trying to cover most cases, using something like:

if (AppDomain.CurrentDomain.IsDefaultAppDomain())
    AppDomain.CurrentDomain.ProcessExit += MyTerminationHandler;
else
    AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler;

但千万注意以下备注(从MSDN )

所有ProcessExit事件处理程序的总执行时间是有限的,正如所有终结的总执行时间的进程关闭限制。默认为两秒钟。非托管主机可以通过调用ICLRPolicyManager :: setTimeout的方法与OPR_ProcessExit枚举值改变这个执行时间。

The total execution time of all ProcessExit event handlers is limited, just as the total execution time of all finalizers is limited at process shutdown. The default is two seconds. An unmanaged host can change this execution time by calling the ICLRPolicyManager::SetTimeout method with the OPR_ProcessExit enumeration value.

以上code仍有第三情景无人值守。 有两种方法我知道的用于与该场景处理(沿与前两个)

The above code still leaves the 3rd scenario unattended. There are two methods I know of for dealing with that scenario (along with the first two)

首先,您可以使用 System.Runtime.CompilerServices.RuntimeHelpers.Execute codeWithGuaranteedCleanup 方法,如下所示:

First, you can use the System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup method, as follows:

{
//  this goes at your code's entry point
    RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(MyExecutionCode, MyCleanupCode, null);
}
static void MyExecutionCode(object data) { /* your execution code here */}
static void MyCleanupCode(object data, bool exceptionThrown) { /* your cleanup code here */ }

二,你可以利用 System.Runtime.ConstrainedExecution.CriticalFinalizerObject 类(请参阅MSDN这里)通过继承它,并把你的清理code中终结。这需要你清理code坚持受约束的执行区域指导方针。

Second, you can utilize the System.Runtime.ConstrainedExecution.CriticalFinalizerObject class (see MSDN here) by inheriting it and putting your cleanup code in the finalizer. This requires your cleanup code to adhere to the Constrained Execution Region guidelines.