vue-java-tutorials/CSharp/WPFTutorial/WPF-25-TreeView/App.xaml.cs

128 lines
3.8 KiB
C#
Raw Normal View History

2025-06-22 20:21:42 +08:00
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Threading;
namespace WPF_25_TreeView;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
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);
}
/// <summary>
/// 处理非UI线程异常
/// </summary>
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);
}
}
/// <summary>
/// 处理UI线程异常可阻止应用崩溃
/// </summary>
private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LogException(e.Exception, "UI线程异常");
ShowUserFriendlyError(e.Exception);
// 标记为已处理,阻止应用崩溃(谨慎使用!)
e.Handled = true;
}
/// <summary>
/// 处理异步任务异常
/// </summary>
private static void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{
LogException(e.Exception, "异步任务异常");
e.SetObserved(); // 标记为已处理,避免进程崩溃
}
/// <summary>
/// 记录异常到日志文件
/// </summary>
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
{
/* 防止日志记录本身抛出异常 */
}
}
/// <summary>
/// 显示用户友好的错误提示
/// </summary>
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
);
}
/// <summary>
/// 显示致命错误并退出
/// </summary>
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);
}
}