更新框架
This commit is contained in:
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(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user