using FluidExplorer.Services; using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; namespace FluidExplorer; public partial class App : Application { /// 启动阶段日志:WinUI 启动期的异常在窗口出现前就终止进程,必须落盘才能定位。 private static readonly string LogPath = Path.Combine(AppContext.BaseDirectory, "startup.log"); public App() { Log("App ctor: begin"); InitializeComponent(); Log("App ctor: InitializeComponent done"); UnhandledException += OnUnhandledException; AppDomain.CurrentDomain.UnhandledException += (_, e) => Log($"AppDomain unhandled: {e.ExceptionObject}"); TaskScheduler.UnobservedTaskException += (_, e) => { Log($"Unobserved task exception: {e.Exception}"); e.SetObserved(); }; // 诊断开关:宿主/非托管路径上的异常不会走 UnhandledException,需要首次异常钩子才能看到来源 if (Environment.GetEnvironmentVariable("FLUID_DEBUG_EXPLOG") == "1") { AppDomain.CurrentDomain.FirstChanceException += (_, e) => { var ex = e.Exception; var stack = ex.StackTrace ?? string.Empty; if (stack.Contains("FluidExplorer", StringComparison.Ordinal) || ex.Source?.Contains("FluidExplorer", StringComparison.Ordinal) == true) Log($"first-chance {ex.GetType().FullName}: {ex.Message}{Environment.NewLine}{stack}"); }; } } public static AppServices Services { get; private set; } = null!; /// 当前主窗口(原版右键菜单、窗口图标、对话框都需要它的 HWND / XamlRoot)。 public static MainWindow MainWindowInstance { get; private set; } = null!; protected override void OnLaunched(LaunchActivatedEventArgs args) { try { Log("OnLaunched: begin"); Services = new AppServices(DispatcherQueue.GetForCurrentThread()); Log("OnLaunched: services ready"); Services.WireSearchIndex(); Log("OnLaunched: search index wired"); MainWindowInstance = new MainWindow(Services); Log("OnLaunched: window constructed"); MainWindowInstance.Activate(); Log("OnLaunched: window activated"); } catch (Exception ex) { Log($"OnLaunched FAILED: {ex}"); throw; } } internal static void Log(string message) { try { File.AppendAllText(LogPath, $"[{DateTime.Now:HH:mm:ss.fff}] {message}{Environment.NewLine}"); } catch { // 日志失败绝不能影响主流程 } } private static void OnUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { Log($"XAML unhandled: {e.Message}{Environment.NewLine}{e.Exception}"); try { var log = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "FluidExplorer", "crash.log"); Directory.CreateDirectory(Path.GetDirectoryName(log)!); File.AppendAllText(log, $"[{DateTime.Now:O}] {e.Message}\n{e.Exception}\n\n"); } catch { // 忽略 } e.Handled = true; } }