using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Threading;
namespace WPF_25_TreeView;
///
/// Interaction logic for App.xaml
///
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
// 全局未处理异常捕获(UI线程和非UI线程)
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
// 专为WPF UI线程异常捕获(例如按钮点击事件中的异常)
DispatcherUnhandledException += OnDispatcherUnhandledException;
// 异步任务异常捕获
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
base.OnStartup(e);
}
///
/// 处理非UI线程异常
///
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is not Exception exception) return;
LogException(exception, "全局异常");
if (e.IsTerminating) // 如果是致命异常
{
ShowFatalError(exception);
Environment.Exit(1); // 确保应用退出
}
else
{
ShowUserFriendlyError(exception);
}
}
///
/// 处理UI线程异常(可阻止应用崩溃)
///
private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LogException(e.Exception, "UI线程异常");
ShowUserFriendlyError(e.Exception);
// 标记为已处理,阻止应用崩溃(谨慎使用!)
e.Handled = true;
}
///
/// 处理异步任务异常
///
private static void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{
LogException(e.Exception, "异步任务异常");
e.SetObserved(); // 标记为已处理,避免进程崩溃
}
///
/// 记录异常到日志文件
///
private static void LogException(Exception ex, string category)
{
var logMessage = $"[{DateTime.Now}] [{category}]\n{ex}\n\n";
try
{
File.AppendAllText("app_errors.log", logMessage);
Debug.WriteLine(logMessage); // 输出到调试窗口
}
catch
{
/* 防止日志记录本身抛出异常 */
}
}
///
/// 显示用户友好的错误提示
///
private static void ShowUserFriendlyError(Exception ex)
{
var message = ex switch
{
UnauthorizedAccessException => $"权限不足: {ex.Message}\n请检查文件/文件夹权限。",
FileNotFoundException => $"文件未找到: {ex.Message}",
IOException => $"文件读写错误: {ex.Message}",
_ => $"发生错误: {(ex.InnerException ?? ex).Message}"
};
MessageBox.Show(
message,
"错误",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
///
/// 显示致命错误并退出
///
private static void ShowFatalError(Exception ex)
{
MessageBox.Show(
$"程序即将关闭,原因:\n{ex.Message}\n\n详细信息已记录到日志。",
"致命错误",
MessageBoxButton.OK,
MessageBoxImage.Stop
);
}
protected override void OnExit(ExitEventArgs e)
{
// 清理事件订阅
AppDomain.CurrentDomain.UnhandledException -= OnUnhandledException;
DispatcherUnhandledException -= OnDispatcherUnhandledException;
TaskScheduler.UnobservedTaskException -= OnUnobservedTaskException;
base.OnExit(e);
}
}