using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using MultiTerm.Core.ViewModel; using System.Windows; using MultiTerm.Core.Helpers; using Common.Logging; using System; using System.Threading.Tasks; using Common.AppSettings; using MultiTerm.Protocols.Helpers; using CommunityToolkit.Mvvm.Messaging; using Common; using System.IO; namespace MultiTerm.Wpf; public partial class App : Application { private static ILogger? logger; public static IHost? AppHost { get; private set; } public App() { // create folder in appdata if it does not exist if (Directory.Exists(Common.BaseAppDataDirectory) == false) { Directory.CreateDirectory(Common.BaseAppDataDirectory); Directory.CreateDirectory(Common.LogFilesDirectory); } // create dependency injection host AppHost = Host.CreateDefaultBuilder() .ConfigureServices((hostContext, services) => { services.AddSingleton(); services.AddSingleton(new WpfContext()); services.AddSingleton(new SerilogLogger($"{Common.LogFilesDirectory}/{Common.LogFileName}", true)); services.AddSingleton(new XmlAppSettingsProvider(Common.ConfigFilePath)); services.AddSingleton(); // viewmodels services.AddSingleton(); // application specific services.AddCommunicationProtocolFactory(); services.AddTerminalViewModelFactory(); }) .Build(); } protected override async void OnStartup(StartupEventArgs e) { await AppHost!.StartAsync(); // create logger and initialize logger = AppHost.Services.GetRequiredService(); logger.Initialize(LogLevel.Trace); logger.LogInfo("Application started.", nameof(App)); // register handlers to some hidden exception types AppDomain.CurrentDomain.UnhandledException += this.AppDomain_UnhandledException; Application.Current.DispatcherUnhandledException += this.Application_DispatcherUnhandledException; TaskScheduler.UnobservedTaskException += this.TaskScheduler_UnobservedTaskException; // register log events from AppSettingsProvider and load saved settings var appSettingsProvider = AppHost.Services.GetRequiredService(); appSettingsProvider.LogWorthyEvent += AppSettingsProvider_LogWorthyEvent; appSettingsProvider.Load(); // instanciate startup form and show var startupForm = AppHost.Services.GetRequiredService(); startupForm.Show(); base.OnStartup(e); } private void AppSettingsProvider_LogWorthyEvent(object? sender, LogEntry e) { logger?.Log(e); } protected override async void OnExit(ExitEventArgs e) { // save settings to persistent location var appSettingsProvider = AppHost!.Services.GetRequiredService(); appSettingsProvider.Save(); // teardown of terminal views and communication protocol threads var shellViewModel = AppHost!.Services.GetRequiredService(); shellViewModel.Teardown(); // log application exit and stop logger (if still available) logger?.LogInfo("Application exited.", nameof(App)); logger?.StopLogging(); await AppHost!.StopAsync(); base.OnExit(e); } #region Event handlers for hidden exceptions private void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { logger?.LogException((Exception)e.ExceptionObject, "AppDomain UnhandledException occurred", nameof(App)); MessageBox.Show("Please check logfile. Exception message: \n" + ((Exception)e.ExceptionObject).Message, "AppDomain UnhandledException occurred", MessageBoxButton.OK, MessageBoxImage.Warning); } private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { logger?.LogException(e.Exception, "Application DispatcherUnhandledException occurred", nameof(App)); MessageBox.Show("Please check logfile. Exception message: \n" + e.Exception.Message, "Application DispatcherUnhandledException occurred", MessageBoxButton.OK, MessageBoxImage.Warning); } private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e) { logger?.LogException(e.Exception, "TaskScheduler UnobservedTaskException occurred", nameof(App)); MessageBox.Show("Please check logfile. Exception message: \n" + e.Exception.Message, "TaskScheduler UnobservedTaskException occurred", MessageBoxButton.OK, MessageBoxImage.Warning); } #endregion }