diff --git a/src/Common.CoreLib/IOPath.cs b/src/Common.CoreLib/IOPath.cs index 6a721baa6..aa3278d68 100644 --- a/src/Common.CoreLib/IOPath.cs +++ b/src/Common.CoreLib/IOPath.cs @@ -240,14 +240,14 @@ namespace System /// /// 判断路径是否为[文件夹(Dir)] /// - /// + /// /// - public static bool IsDirectory(string IOPath) + public static bool IsDirectory(string path) { #if NET35 throw new PlatformNotSupportedException(); #else - var attr = File.GetAttributes(IOPath); + var attr = File.GetAttributes(path); return attr.HasFlag(FileAttributes.Directory); #endif } @@ -257,21 +257,21 @@ namespace System /// 如果传入的参数为[文件(File)]路径,则返回当前所在[文件夹(Dir)]路径 /// 如果传入的参数为[文件夹(Dir)]路径,则直接返回参数 /// - /// + /// /// - public static string GetDirectoryPath(string IOPath) + public static string GetDirectoryPath(string path) { try { - if (!IsDirectory(IOPath)) + if (!IsDirectory(path)) { - return Path.GetDirectoryName(IOPath) ?? string.Empty; + return Path.GetDirectoryName(path) ?? string.Empty; } } catch { } - return IOPath; + return path; } static FileStream OpenReadCore(string filePath) => new(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); diff --git a/src/Common.CoreLib/Properties/ThisAssembly.DynamicVersion.cs b/src/Common.CoreLib/Properties/ThisAssembly.DynamicVersion.cs index b855a81c4..aedffa520 100644 --- a/src/Common.CoreLib/Properties/ThisAssembly.DynamicVersion.cs +++ b/src/Common.CoreLib/Properties/ThisAssembly.DynamicVersion.cs @@ -14,7 +14,7 @@ namespace System.Properties case Platform.Linux: return Version + alpha; case Platform.Android: - return Version + beta; + return Version + alpha; case Platform.Apple: switch (DI.DeviceIdiom) { diff --git a/src/ST.Client.Desktop.Avalonia.App.Bridge/Bin.csproj b/src/ST.Client.Desktop.Avalonia.App.Bridge/Bin.csproj index 40046bd4a..53bec9102 100644 --- a/src/ST.Client.Desktop.Avalonia.App.Bridge/Bin.csproj +++ b/src/ST.Client.Desktop.Avalonia.App.Bridge/Bin.csproj @@ -30,6 +30,7 @@ + Properties\AssemblyInfo.cs diff --git a/src/ST.Client.Desktop.Avalonia.App/Program.cs b/src/ST.Client.Desktop.Avalonia.App/Program.cs index 715621ea3..e4f8b1d82 100644 --- a/src/ST.Client.Desktop.Avalonia.App/Program.cs +++ b/src/ST.Client.Desktop.Avalonia.App/Program.cs @@ -1,17 +1,11 @@ using NLog; -using ReactiveUI; -using System.Application.Services; using System.Collections.Generic; using System.Linq; -using System.Reactive; -using AvaloniaApplication = Avalonia.Application; -using LogLevel = Microsoft.Extensions.Logging.LogLevel; namespace System.Application.UI { static partial class Program { - static Logger? logger; static readonly HashSet exceptions = new(); static readonly object lock_global_ex_log = new(); @@ -27,7 +21,6 @@ namespace System.Application.UI #if MAC AppDelegateHelper.Init(args); FileSystemDesktopMac.InitFileSystem(); - //FileSystemDesktop.InitFileSystem(); #else FileSystemDesktop.InitFileSystem(); #endif @@ -48,19 +41,7 @@ namespace System.Application.UI void InitCefNetApp() => CefNetApp.Init(AppHelper.LogDirPath, args); void InitAvaloniaApp() => BuildAvaloniaAppAndStartWithClassicDesktopLifetime(args); void InitStartup(DILevel level) => Startup.Init(level); - logger = LogManager.GetCurrentClassLogger(); - AppDomain.CurrentDomain.UnhandledException += (_, e) => - { - if (e.ExceptionObject is Exception ex) - { - HandleGlobalException(ex, nameof(AppDomain.UnhandledException), e.IsTerminating); - } - }; - RxApp.DefaultExceptionHandler = Observer.Create(ex => - { - // https://github.com/AvaloniaUI/Avalonia/issues/5290#issuecomment-760751036 - HandleGlobalException(ex, nameof(RxApp.DefaultExceptionHandler)); - }); + Startup.InitGlobalExceptionHandler(); try { string[] args_clt; @@ -77,7 +58,7 @@ namespace System.Application.UI } catch (Exception ex) { - HandleGlobalException(ex, nameof(Main)); + Startup.GlobalExceptionHandler(ex, nameof(Main)); throw; } finally @@ -87,85 +68,12 @@ namespace System.Application.UI LogManager.Shutdown(); ArchiSteamFarm.LogManager.Shutdown(); } - - static void HandleGlobalException(Exception ex, string name, bool? isTerminating = null) - { - lock (lock_global_ex_log) - { - if (exceptions.Contains(ex)) return; - exceptions.Add(ex); - } - - AppHelper.TrySetLoggerMinLevel(LogLevel.Trace); - // NLog: catch any exception and log it. - logger?.Error(ex, "Stopped program because of exception, name: {1}, isTerminating: {0}", isTerminating, name); - - try - { - DI.Get().StopProxy(); - ProxyService.OnExitRestoreHosts(); - } - catch (Exception ex_restore_hosts) - { - logger?.Error(ex_restore_hosts, "(App)Close exception when OnExitRestoreHosts"); - } - - var callTryShutdown = true; - try - { - callTryShutdown = !App.Shutdown(); - } - catch (Exception ex_shutdown) - { - logger?.Error(ex_shutdown, - "(App)Close exception when exception occurs"); - } - - if (callTryShutdown) - { - try - { - AppHelper.TryShutdown(); - } - catch (Exception ex_shutdown_app_helper) - { - logger?.Error(ex_shutdown_app_helper, - "(AppHelper)Close exception when exception occurs"); - } - } - - try - { - if (AvaloniaApplication.Current is App app) - { - app.compositeDisposable.Dispose(); - } - } - catch - { - } - -#if DEBUG - //MessageBoxCompat.Show(ex.ToString(), "Steam++ Run Error" + ThisAssembly.Version, MessageBoxButtonCompat.OK, MessageBoxImageCompat.Warning); -#endif - -#if DEBUG && WINDOWS - if (ex.InnerException is BadImageFormatException) - { - typeof(Program).Assembly.ManifestModule.GetPEKind(out var peKind, out var _); - if (!peKind.HasFlag(Reflection.PortableExecutableKinds.Required32Bit)) - { - logger?.Error("Some references need to work on X86 platforms."); - } - } -#endif - } } /// /// 是否最小化启动 /// - public static bool IsMinimize { get; /*private*/ set; } + public static bool IsMinimize { get; set; } /// /// 当前是否是命令行工具进程 diff --git a/src/ST.Client.Desktop.Avalonia.App/ST.Client.Desktop.Avalonia.App.csproj b/src/ST.Client.Desktop.Avalonia.App/ST.Client.Desktop.Avalonia.App.csproj index ab1c9bb28..7fb49ad74 100644 --- a/src/ST.Client.Desktop.Avalonia.App/ST.Client.Desktop.Avalonia.App.csproj +++ b/src/ST.Client.Desktop.Avalonia.App/ST.Client.Desktop.Avalonia.App.csproj @@ -70,6 +70,7 @@ + Properties\AssemblyInfo.cs @@ -144,22 +145,19 @@ + - - - - diff --git a/src/ST.Client.Desktop.Mac/ST.Client.Desktop.Mac.csproj b/src/ST.Client.Desktop.Mac/ST.Client.Desktop.Mac.csproj index 72b2ff5b6..4ffcb653d 100644 --- a/src/ST.Client.Desktop.Mac/ST.Client.Desktop.Mac.csproj +++ b/src/ST.Client.Desktop.Mac/ST.Client.Desktop.Mac.csproj @@ -74,10 +74,10 @@ + - diff --git a/src/ST.Client.Desktop.Windows/ST.Client.Desktop.Windows.csproj b/src/ST.Client.Desktop.Windows/ST.Client.Desktop.Windows.csproj index a61f08858..74dfe481e 100644 --- a/src/ST.Client.Desktop.Windows/ST.Client.Desktop.Windows.csproj +++ b/src/ST.Client.Desktop.Windows/ST.Client.Desktop.Windows.csproj @@ -45,10 +45,10 @@ + - diff --git a/src/ST.Client.Desktop.Windows/VisualStudioAppCenterSDK.cs b/src/ST.Client.Desktop.Windows/VisualStudioAppCenterSDK.cs index 305eb37fd..b8ede029b 100644 --- a/src/ST.Client.Desktop.Windows/VisualStudioAppCenterSDK.cs +++ b/src/ST.Client.Desktop.Windows/VisualStudioAppCenterSDK.cs @@ -47,7 +47,7 @@ namespace System.Application { var assembly = typeof(VisualStudioAppCenterSDK).Assembly; const string namespacePrefix = "System.Application.Resources."; - Stream? func(string x) => assembly.GetManifestResourceStream(x); + Stream? func(string x) => assembly!.GetManifestResourceStream(x); var r = GetResValue(func, #if XAMARIN_MAC || MONO_MAC || MAC "appcenter-secret-mac", diff --git a/src/ST.Client.Mobile.Droid/ST.Client.Mobile.Droid.csproj b/src/ST.Client.Mobile.Droid/ST.Client.Mobile.Droid.csproj index 5c538c3b9..01a7177fa 100644 --- a/src/ST.Client.Mobile.Droid/ST.Client.Mobile.Droid.csproj +++ b/src/ST.Client.Mobile.Droid/ST.Client.Mobile.Droid.csproj @@ -9,6 +9,7 @@ + Properties\AssemblyInfo.cs @@ -166,34 +167,30 @@ + - + - - + + - - - - - diff --git a/src/ST.Client.Mobile.Droid/UI/MainApplication.cs b/src/ST.Client.Mobile.Droid/UI/MainApplication.cs index a05ecbb59..61a4b5535 100644 --- a/src/ST.Client.Mobile.Droid/UI/MainApplication.cs +++ b/src/ST.Client.Mobile.Droid/UI/MainApplication.cs @@ -60,6 +60,8 @@ namespace System.Application.UI AppHelper.InitLogDir(); + Startup.InitGlobalExceptionHandler(); + VisualStudioAppCenterSDK.Init(); XEFileProvider.TemporaryLocation = FileProviderLocation.Internal; diff --git a/src/Startup2.HandleGlobalException.cs b/src/Startup2.HandleGlobalException.cs new file mode 100644 index 000000000..149d6995e --- /dev/null +++ b/src/Startup2.HandleGlobalException.cs @@ -0,0 +1,108 @@ +using NLog; +using ReactiveUI; +using System.Application.Services; +using System.Application.UI; +using System.Collections.Generic; +using System.Reactive; +#if !__MOBILE__ +using AvaloniaApplication = Avalonia.Application; +#endif +using LogLevel = Microsoft.Extensions.Logging.LogLevel; + +namespace System.Application +{ + partial class Startup + { + static readonly Lazy _logger = new(LogManager.GetCurrentClassLogger); + static Logger? Logger => _logger.Value; + static readonly HashSet exceptions = new(); + static readonly object lock_global_ex_log = new(); + + /// + /// 初始化全局异常处理 + /// + public static void InitGlobalExceptionHandler() + { + AppDomain.CurrentDomain.UnhandledException += (_, e) => + { + if (e.ExceptionObject is Exception ex) + { + GlobalExceptionHandler(ex, nameof(AppDomain.UnhandledException), e.IsTerminating); + } + }; + RxApp.DefaultExceptionHandler = Observer.Create(ex => + { + // https://github.com/AvaloniaUI/Avalonia/issues/5290#issuecomment-760751036 + GlobalExceptionHandler(ex, nameof(RxApp.DefaultExceptionHandler)); + }); + } + + /// + /// 全局异常处理 + /// + /// + /// + /// + public static void GlobalExceptionHandler(Exception ex, string name, bool? isTerminating = null) + { + lock (lock_global_ex_log) + { + if (exceptions.Contains(ex)) return; + exceptions.Add(ex); + } + + AppHelper.TrySetLoggerMinLevel(LogLevel.Trace); + // NLog: catch any exception and log it. + Logger?.Error(ex, "Stopped program because of exception, name: {1}, isTerminating: {0}", isTerminating, name); + +#if !__MOBILE__ + try + { + DI.Get().StopProxy(); + ProxyService.OnExitRestoreHosts(); + } + catch (Exception ex_restore_hosts) + { + Logger?.Error(ex_restore_hosts, "(App)Close exception when OnExitRestoreHosts"); + } +#endif + +#if !__MOBILE__ + var callTryShutdown = true; + try + { + callTryShutdown = !App.Shutdown(); + } + catch (Exception ex_shutdown) + { + Logger?.Error(ex_shutdown, + "(App)Close exception when exception occurs"); + } + + if (callTryShutdown) + { + try + { + AppHelper.TryShutdown(); + } + catch (Exception ex_shutdown_app_helper) + { + Logger?.Error(ex_shutdown_app_helper, + "(AppHelper)Close exception when exception occurs"); + } + } + + try + { + if (AvaloniaApplication.Current is App app) + { + app.compositeDisposable.Dispose(); + } + } + catch + { + } +#endif + } + } +} \ No newline at end of file diff --git a/src/Startup2.cs b/src/Startup2.cs index c1dc4b145..0e3fd8d49 100644 --- a/src/Startup2.cs +++ b/src/Startup2.cs @@ -43,7 +43,7 @@ using _ThisAssembly = System.Properties.ThisAssembly; namespace System.Application { - static class Startup + static partial class Startup { static bool isInitialized;