// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! namespace Admin.NET.Web.Entry; /// /// 进程级未处理异常:在 DI/日志管道就绪前尽量落盘到控制台,便于容器与本地排障。 /// 说明:.NET 中 IsTerminating 时无法阻止进程退出,仅能最后记录。 /// public static class GlobalProcessExceptionHandlers { private static int _registered; public static void Register() { if (Interlocked.Exchange(ref _registered, 1) != 0) return; AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; TaskScheduler.UnobservedTaskException += OnUnobservedTaskException; } private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) { try { var terminating = e.IsTerminating ? "即将终止进程" : "非终止"; var ex = e.ExceptionObject as Exception; var headline = $"[{DateTime.UtcNow:O}] AppDomain 未处理异常 ({terminating})"; Console.Error.WriteLine(headline); if (ex != null) Console.Error.WriteLine(ex); else Console.Error.WriteLine(e.ExceptionObject); } catch { // 避免回调内再抛导致二次崩溃 } } private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { try { Console.Error.WriteLine($"[{DateTime.UtcNow:O}] TaskScheduler 未观察到的任务异常:"); Console.Error.WriteLine(e.Exception); e.SetObserved(); } catch { try { e.SetObserved(); } catch { // ignore } } } }