Нет прямого ответа, о котором я знаю.
Если вы хотите, чтобы написать надежный DLL, вы должны подготовить несколько сценариев:
- Ваш код размещается в приложении .NET, в AppDomain по умолчанию. (тривиальный сценарий)
- Ваш код размещен в приложении .NET в AppDomain, созданном кодом хоста.
- Ваш код размещен в неуправляемом приложении (в котором размещается CLR).
Третий сценарий сложнее, поскольку CLR может быть отключен его хостом, поэтому управляемый код больше не будет выполняться.
System.Windows.Forms.Application.ApplicationExit
не подходит, поскольку применяется только к приложениям WinForm.
System.AppDomain.DomainUnload
сам по себе не годится, поскольку он никогда не поднимается для стандартного AppDomain.
AppDomain.ProcessExit
сам по себе не годится: если ваш код размещен в отдельном AppDomain, хост может выгрузить этот AppDomain, поэтому событие никогда не будет повышаться.
Я хотел бы начать, пытаясь охватить большинство случаев, используя что-то вроде:
if (AppDomain.CurrentDomain.IsDefaultAppDomain())
AppDomain.CurrentDomain.ProcessExit += MyTerminationHandler;
else
AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler;
Но не заметить следующее замечание (from MSDN):
Общее время выполнения всех события ProcessExit обработчики ограничены, так же как общее время выполнения всех финализаторов ограничено при завершении процесса. Значение по умолчанию - две секунды. Неуправляемый хост может изменить это время выполнения, вызвав метод ICLRPolicyManager :: SetTimeout с параметром перечисления OPR_ProcessExit.
Приведенный выше код по-прежнему оставляет 3-й сценарий без присмотра. Есть два способа я знаю для решения этого сценария (вместе с первым два)
Во-первых, вы можете использовать метод System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup
следующим образом:
{
// 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
class (see MSDN here), наследуя его и помещая ваш код очистки в финализатор. Это требует, чтобы ваш код очистки придерживался руководящих принципов Constrained Execution Region.
Вы можете попробовать CTRL_CLOSE_EVENT событие SetConsoleCtrlHandler. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx –