From d683cfd24155a8f5bd0c2fb8661ed41e887a4c32 Mon Sep 17 00:00:00 2001 From: AlexAlves87 Date: Sun, 31 May 2026 01:15:33 +0200 Subject: [PATCH] refactor: extract AppCrashLogger from App.xaml.cs Move the crash-logging sink (LogCrash + CrashLogPath) out of App.xaml.cs into a dedicated AppCrashLogger, mirroring the existing AppRunMarker. The three unhandled-exception handlers and the ShowTrayMenuPopup catch now delegate to the instance; behavior is byte-for-byte identical. Co-Authored-By: Claude Sonnet 4.6 --- src/OpenClaw.Tray.WinUI/App.xaml.cs | 37 +++-------------- .../Services/AppCrashLogger.cs | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 32 deletions(-) create mode 100644 src/OpenClaw.Tray.WinUI/Services/AppCrashLogger.cs diff --git a/src/OpenClaw.Tray.WinUI/App.xaml.cs b/src/OpenClaw.Tray.WinUI/App.xaml.cs index 51b1d1970..e234768a0 100644 --- a/src/OpenClaw.Tray.WinUI/App.xaml.cs +++ b/src/OpenClaw.Tray.WinUI/App.xaml.cs @@ -197,7 +197,7 @@ public IntPtr GetHubWindowHandle() Environment.GetEnvironmentVariable("OPENCLAW_TRAY_APPDATA_DIR") ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "OpenClawTray"); - private static readonly string CrashLogPath = Path.Combine(DataPath, "crash.log"); + private readonly AppCrashLogger _crashLogger = new(Path.Combine(DataPath, "crash.log")); private static readonly AppRunMarker s_runMarker = new(Path.Combine(DataPath, "run.marker")); private const string DisableMouseInPointerEnv = "OPENCLAW_DISABLE_MOUSE_IN_POINTER"; @@ -289,18 +289,18 @@ value is not null && private void OnUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { - LogCrash("UnhandledException", e.Exception); + _crashLogger.Log("UnhandledException", e.Exception); e.Handled = true; // Try to prevent crash } private void OnDomainUnhandledException(object sender, System.UnhandledExceptionEventArgs e) { - LogCrash("DomainUnhandledException", e.ExceptionObject as Exception); + _crashLogger.Log("DomainUnhandledException", e.ExceptionObject as Exception); } private void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e) { - LogCrash("UnobservedTaskException", e.Exception); + _crashLogger.Log("UnobservedTaskException", e.Exception); e.SetObserved(); // Prevent crash } @@ -314,33 +314,6 @@ private void OnProcessExit(object? sender, EventArgs e) catch { } } - private static void LogCrash(string source, Exception? ex) - { - try - { - var dir = Path.GetDirectoryName(CrashLogPath); - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - Directory.CreateDirectory(dir); - - var message = $"\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {source}\n{ex}\n"; - File.AppendAllText(CrashLogPath, message); - } - catch { /* Can't log the crash logger crash */ } - - try - { - if (ex != null) - { - Logger.Error($"CRASH {source}: {ex}"); - } - else - { - Logger.Error($"CRASH {source}"); - } - } - catch { /* Ignore logging failures */ } - } - private void OnUiThread(Microsoft.UI.Dispatching.DispatcherQueueHandler action) => _dispatcherQueue?.TryEnqueue(action); /// @@ -871,7 +844,7 @@ private void ShowTrayMenuPopup() } catch (Exception ex) { - LogCrash("ShowTrayMenuPopup", ex); + _crashLogger.Log("ShowTrayMenuPopup", ex); Logger.Error($"Failed to show tray menu: {ex.Message}"); } } diff --git a/src/OpenClaw.Tray.WinUI/Services/AppCrashLogger.cs b/src/OpenClaw.Tray.WinUI/Services/AppCrashLogger.cs new file mode 100644 index 000000000..c5d987dc2 --- /dev/null +++ b/src/OpenClaw.Tray.WinUI/Services/AppCrashLogger.cs @@ -0,0 +1,40 @@ +namespace OpenClawTray.Services; + +/// +/// Writes crash details to a log file and the application logger. Hooked from the WinUI, +/// CLR domain, and TaskScheduler unhandled-exception events, which may fire on the UI +/// thread or background threads. +/// +internal sealed class AppCrashLogger +{ + private readonly string _path; + + public AppCrashLogger(string path) => _path = path; + + public void Log(string source, Exception? ex) + { + try + { + var dir = Path.GetDirectoryName(_path); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + var message = $"\n[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {source}\n{ex}\n"; + File.AppendAllText(_path, message); + } + catch { /* Can't log the crash logger crash */ } + + try + { + if (ex != null) + { + Logger.Error($"CRASH {source}: {ex}"); + } + else + { + Logger.Error($"CRASH {source}"); + } + } + catch { /* Ignore logging failures */ } + } +}