In C
there is the atexit function, which
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 has a similar capability.
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.
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.
Use ExitCode to get the status that the system process returned when it exited. You can use the exit code much like an integer return value from a main() procedure. The ExitCode value for a process reflects the specific convention implemented by the application developer for that process.
Exit codes above 128 have a special meaning—when a process is terminated by a signal, its exit code is 128 plus the signal number.
You can use Process. GetProcessesByName Method (String) to find whether a particular process is running or not.
There is no straight-forward answer that I know of.
If you want to write a robust DLL, you should prepare for several scenarios:
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
is no good since it only applies to WinForm applications.
System.AppDomain.DomainUnload
by itself is no good since it is never raised for the default 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;
But do notice the following remark (from MSDN):
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.
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)
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 */ }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With