Files
LanMountainDesktop/LanDesktopPLONDS.installer/InstallerStartupDiagnostics.cs
2026-06-09 22:18:27 +08:00

93 lines
2.8 KiB
C#

using System.Runtime.InteropServices;
using System.Text;
namespace LanDesktopPLONDS.Installer;
internal static class InstallerStartupDiagnostics
{
private const uint MessageBoxIconError = 0x00000010;
private const uint MessageBoxOk = 0x00000000;
private static int _initialized;
private static int _fatalMessageShown;
public static string LogPath => Path.Combine(GetLogDirectory(), "startup.log");
public static void Initialize()
{
if (Interlocked.Exchange(ref _initialized, 1) != 0)
{
return;
}
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
{
var exception = args.ExceptionObject as Exception;
ReportFatal("The installer encountered an unhandled startup error.", exception);
};
TaskScheduler.UnobservedTaskException += (_, args) =>
{
ReportFatal("The installer encountered an unobserved background error.", args.Exception);
args.SetObserved();
};
Log("Startup diagnostics initialized.");
}
public static void Log(string message)
{
try
{
Directory.CreateDirectory(GetLogDirectory());
File.AppendAllText(
LogPath,
$"[{DateTimeOffset.Now:O}] {message}{Environment.NewLine}",
Encoding.UTF8);
}
catch
{
// Diagnostics must never become the reason the installer cannot start.
}
}
public static void ReportFatal(string message, Exception? exception)
{
Log(exception is null ? message : $"{message}{Environment.NewLine}{exception}");
if (!OperatingSystem.IsWindows() || Interlocked.Exchange(ref _fatalMessageShown, 1) != 0)
{
return;
}
try
{
var details = exception is null
? message
: $"{message}{Environment.NewLine}{Environment.NewLine}{exception.GetType().Name}: {exception.Message}";
_ = MessageBox(
IntPtr.Zero,
$"{details}{Environment.NewLine}{Environment.NewLine}Log: {LogPath}",
"LanDesktopPLONDS Installer",
MessageBoxOk | MessageBoxIconError);
}
catch
{
}
}
private static string GetLogDirectory()
{
var root = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (string.IsNullOrWhiteSpace(root))
{
root = AppContext.BaseDirectory;
}
return Path.Combine(root, "LanMountainDesktop", "Installer", "logs");
}
[DllImport("user32.dll", EntryPoint = "MessageBoxW", CharSet = CharSet.Unicode)]
private static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
}