Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 5 additions & 32 deletions src/OpenClaw.Tray.WinUI/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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
}

Expand All @@ -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);

/// <summary>
Expand Down Expand Up @@ -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}");
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/OpenClaw.Tray.WinUI/Services/AppCrashLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace OpenClawTray.Services;

/// <summary>
/// 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.
/// </summary>
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 */ }
}
}
Loading