更新框架

This commit is contained in:
chfei committed 2026-10-27 14:35:03 +08:00
1 parent ef50fa0620
commit 84b28f9672
72 files changed
+2222 -282

No files matched your search

@@ -1,51 +1,150 @@
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Store.Management.Framework.Extensions;
using MAX.Framework.Logger;
using NLog;
using Prism.Autofac;
using Prism.Ioc;
using Prism.Services.Dialogs;
using Store.Management.Framework.Configs;
using Store.Management.Framework.Extensions;
using Store.Management.Framework.Services;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
namespace Store.Management.Framework;
public abstract class FrameworkApplication : PrismApplication
{
private Mutex? _mutex;
private bool _ownsMutex;
private int _fatalHandling;
private int _shutdownRequested;
public static bool ShuttingDown { get; private set; }
public static bool IsAppInitialized { get; private set; }
public static event Action<Exception>? FatalErrorRaised;
protected FrameworkApplication()
{
protected FrameworkApplication()
{
DispatcherUnhandledException += OnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += OnDomainUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
}
}
/// <summary>返回 null 可允许多开;默认限制同一登录会话中的应用实例。</summary>
public virtual string? GetMutexName() => @"Local\Store.Management";
protected override void OnStartup(StartupEventArgs e)
{
try
{
//string? name = GetMutexName();
//if (!string.IsNullOrWhiteSpace(name))
//{
// _mutex = new Mutex(true, name, out _ownsMutex);
// if (!_ownsMutex)
// {
// MessageBox.Show("程序已在运行。", Config.AppName, MessageBoxButton.OK, MessageBoxImage.Information);
// Shutdown();
// return;
// }
//}
FolderConfig.Initialize();
base.OnStartup(e);
ApplicationLogService.Initialize();
NLogger.Instance.Info($"软件启动:{Config.AppFullName},版本:{Config.GetFullVersionString()},会话:{Config.SessionID},启动时间:{Config.AppStartTime:O},Windows:{Config.WindowsVersion}");
DISource.Resolver = Resolve;
}
catch (Exception ex) { Fatal(ex); }
}
protected override void OnStartup(StartupEventArgs e)
{
DISource.Resolver = Resolve;
base.OnStartup(e);
}
protected override void OnInitialized()
{
base.OnInitialized();
IsAppInitialized = true;
NLogger.Instance.Info("软件初始化成功,进入主页面");
}
protected override void OnInitialized()
{
(Container as IContainerExtension).RegisterDialog<DialogWindow>();
base.OnInitialized();
}
protected override void RegisterRequiredTypes(IContainerRegistry registry)
{
base.RegisterRequiredTypes(registry);
registry.RegisterDialogWindow<Controls.DialogWindow>();
}
private object Resolve(Type type, string name)
{
if (type == null || Container is null) return null!;
return name != null ? Container.Resolve(type, name) : Container.Resolve(type);
}
private object Resolve(Type type, string name)
{
if (type == null || Container is null)
{
return null;
}
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
Fatal(e.Exception);
}
if (name != null)
{
return Container.Resolve(type, name);
}
private void OnDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exception = e.ExceptionObject as Exception ?? new Exception(e.ExceptionObject?.ToString());
// CLR 终止期间同步记录,不等待 UI 线程。
if (e.IsTerminating) ApplicationLogService.WriteFatal(exception, "AppDomain.UnhandledException");
else Fatal(exception);
}
return Container.Resolve(type);
}
private void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{
ApplicationLogService.WriteFatal(e.Exception, "TaskScheduler.UnobservedTaskException");
e.SetObserved();
}
/// <summary>先同步保存报告,再通知订阅者并关闭应用。</summary>
public static void Fatal(Exception exception)
{
ArgumentNullException.ThrowIfNull(exception);
string? path = ApplicationLogService.WriteFatal(exception, "Fatal");
if (Current is not FrameworkApplication app || Interlocked.Exchange(ref app._fatalHandling, 1) != 0) return;
foreach (Action<Exception> handler in FatalErrorRaised?.GetInvocationList() ?? [])
{
try { handler(exception); }
catch (Exception ex) { ApplicationLogService.WriteFatal(ex, "FatalErrorRaised"); }
}
void ShowErrorAndShutdown()
{
try
{
MessageBox.Show($"软件发生致命错误,即将关闭。\n{exception.Message}\n\n日志:{path ?? "写入失败,请查看调试输出"}",
Config.AppName, MessageBoxButton.OK, MessageBoxImage.Error);
}
finally { TotalShutdown(-1); }
}
if (app.Dispatcher.CheckAccess()) ShowErrorAndShutdown();
else if (!app.Dispatcher.HasShutdownStarted) app.Dispatcher.BeginInvoke((Action)ShowErrorAndShutdown);
}
/// <summary>通过 WPF 正常退出,执行退出清理。</summary>
public static void TotalShutdown(int exitCode = 0)
{
if (Current is not FrameworkApplication app || Interlocked.Exchange(ref app._shutdownRequested, 1) != 0) return;
ShuttingDown = true;
if (app.Dispatcher.CheckAccess()) app.Shutdown(exitCode);
else if (!app.Dispatcher.HasShutdownStarted) app.Dispatcher.BeginInvoke((Action)(() => app.Shutdown(exitCode)));
}
protected override void OnExit(ExitEventArgs e)
{
ShuttingDown = true;
try { base.OnExit(e); }
finally
{
DispatcherUnhandledException -= OnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException -= OnDomainUnhandledException;
TaskScheduler.UnobservedTaskException -= OnUnobservedTaskException;
DISource.Resolver = null!;
try { if (_ownsMutex) _mutex?.ReleaseMutex(); }
finally
{
_mutex?.Dispose();
try { NLogger.Instance.Info($"软件关闭,退出码:{e.ApplicationExitCode}"); }
finally { LogManager.Shutdown(); }
}
}
}
}