Nie ma prostej odpowiedzi, którą znam.
Jeśli chcesz napisać solidną DLL, należy przygotować kilka scenariuszy:
- Kod jest obsługiwana w aplikacji .NET, w domyślnym AppDomain. (banalny scenariusz)
- Twój kod jest hostowany w aplikacji .NET w AppDomain utworzonym przez kod hosta.
- Twój kod jest przechowywany w niezarządzanej aplikacji (która jest hostem CLR).
Trzeci scenariusz jest najtrudniejszy do rozwiązania, ponieważ CLR może być wyłączony przez hosta, więc kod zarządzany nie będzie już wykonywany.
System.Windows.Forms.Application.ApplicationExit
nie jest dobry, ponieważ dotyczy tylko aplikacji WinForm.
System.AppDomain.DomainUnload
samo w sobie nie jest dobre, ponieważ nigdy nie jest wywoływane z domyślnym AppDomain.
AppDomain.ProcessExit
samo w sobie nie jest dobre: jeśli twój kod jest hostowany w oddzielnym AppDomain, host może zwolnić tę aplikację AppDomain, więc wydarzenie nigdy się nie podniesie.
zacząłbym od próby na pokrycie większości przypadków, używając coś takiego:
if (AppDomain.CurrentDomain.IsDefaultAppDomain())
AppDomain.CurrentDomain.ProcessExit += MyTerminationHandler;
else
AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler;
Ale zrobić zauważyć następującą uwagę (from MSDN):
Całkowity czas wykonania całej imprezy ProcessExit Obsługa handlowa jest ograniczona, podobnie jak całkowity czas wykonania wszystkich finalizatorów jest ograniczony przy zamykaniu procesu. Wartość domyślna to dwie sekundy. Host niezarządzany może zmienić ten czas wykonywania, wywołując metodę ICLRPolicyManager :: SetTimeout z wartością wyliczenia OPR_ProcessExit.
Powyższy kod nadal pozostawia trzeci scenariusz bez nadzoru. Istnieją dwie metody znam do czynienia z tego scenariusza (wraz z dwoma pierwszymi)
pierwsze, można użyć metody System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup
, w następujący sposób:
{
// 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 */ }
Po drugie, można wykorzystać System.Runtime.ConstrainedExecution.CriticalFinalizerObject
klasa (see MSDN here), dziedzicząc go i umieszczając kod oczyszczający w finalizatorze. Wymaga to, aby kod porządkowy był zgodny z wytycznymi Constrained Execution Region.
Możesz spróbować zdarzenia CTRL_CLOSE_EVENT SetConsoleCtrlHandler. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx –