using Newtonsoft.Json; using SciChart.Charting.Visuals; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Markup; using Tango.Core.DI; using Tango.Core.Helpers; using Tango.FSE.BL; using Tango.FSE.Common; using Tango.FSE.Common.BugReporting; using Tango.FSE.Common.FileAssociation; using Tango.FSE.Common.Helpers; using Tango.FSE.Common.Notifications; using Tango.FSE.UI.FileAssociation; using Tango.Integration.Operation; using Tango.Logging; using Tango.Settings; using ZetaIpc.Runtime.Client; namespace Tango.FSE.UI { /// /// Interaction logic for App.xaml /// public partial class App : Application { private WpfGlobalExceptionTrapper exceptionTrapper; private LogManager LogManager = LogManager.Default; private HashSet _ignoredGlobalExceptions; public static bool IsStartedAfterCrash { get; private set; } public static String StartedAfterCrashError { get; private set; } private static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F0TANGOFSE}"); public App() : base() { _ignoredGlobalExceptions = new HashSet(); if (!DesignModeHelper.IsInDesignMode()) { Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri(@"/MahApps.Metro;component/Styles/Colors.xaml", UriKind.Relative) }); Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri(@"/MahApps.Metro;component/Styles/Accents/BaseDark.xaml", UriKind.Relative) }); Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri(@"/MahApps.Metro;component/Styles/VS/Colors.xaml", UriKind.Relative) }); Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri(@"/MahApps.Metro;component/Styles/VS/Styles.xaml", UriKind.Relative) }); Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri(@"/MahApps.Metro;component/Styles/Controls.xaml", UriKind.Relative) }); } } protected override void OnStartup(StartupEventArgs e) { try { if (e.Args != null) { var args = StartupArgsHelper.CleanArgsFromWeb(e.Args); if (args.Length == DefaultFileAssociationProvider.FILE_ASSOCIATION_ARGS_COUNT) { if (args[0] == DefaultFileAssociationProvider.FILE_ASSOCIATION_PREFIX) { if (mutex.WaitOne(TimeSpan.Zero, true)) { //This is the first instance. Do nothing... mutex.ReleaseMutex(); } else { //MessageBox.Show($"Run Procedure {e.Args[2]} on another instance."); var settings = SettingsManager.Default.GetOrCreate(); var ipcClient = new IpcClient(); ipcClient.Initialize(settings.FileAssociationServicePort); ipcClient.Send(JsonConvert.SerializeObject(new FileAssociationPackage() { TargetName = args[1], File = args[2] })); Thread.Sleep(1000); Environment.Exit(0); return; } } } } } catch (Exception ex) { Debug.WriteLine(ex); } //Set culture info. var enUSCulture = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = enUSCulture; Thread.CurrentThread.CurrentUICulture = enUSCulture; CultureInfo.DefaultThreadCurrentCulture = enUSCulture; CultureInfo.DefaultThreadCurrentUICulture = enUSCulture; FrameworkElement.LanguageProperty.OverrideMetadata( typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))); //May cause problems. //ThreadPool.SetMaxThreads(1000, 1000); ThreadsHelper.SetDisptacher(Dispatcher); //If no debugger is attached and the argument -debug was passed launch the debugger. if (e.Args.Contains("-debug") && !Debugger.IsAttached) { Debugger.Launch(); } //LogManager.RegisterLogger(new ConsoleLogger("Tango FSE Debug")); LogManager.RegisterLogger(new FileLogger() { EnableAutoLogRemoval = true, EnableMaxFileSizeLimit = true }); LogManager.RegisterLogger(new VSOutputLogger()); //Configure machine operator logger. var operatorLogger = MachineOperator.EmbeddedLogManager.RegisteredLoggers.SingleOrDefault(x => x is FileLogger) as FileLogger; if (operatorLogger != null) { operatorLogger.EnableAutoLogRemoval = true; operatorLogger.EnableMaxFileSizeLimit = true; } LogsHelper.SetLogSafe(LogManager.CreateLogSafe()); LogManager.Log($"Application Started... Version: '{AssemblyHelper.GetCurrentAssemblyVersion()}'."); WebRequest.DefaultWebProxy = null; try { EntityFrameworkExtensionsHelper.SetupLicense("4578;101-twine-s.com", "9d23b66f-1101-b253-7f8a-59ae011b2ee8"); } catch (Exception ex) { LogManager.Log(ex, "Error performing EF extensions license setup."); } try { SciChartSurface.SetRuntimeLicenseKey("27FuI+bWcfmLHSBlM4B8nUs23aeeXvft2+7Pxj0fOrcnruWXyOm/swjI2PpoBPOKS9dNVtw60E4Xdpq4Ts8UgMWQHU8qcJtPoAyNQqbVMQNOr/sv1QpSD2mRjogERcrGty+tvlCHMGhkw/TOiL5DPnw5rOPqGfymyRuJRNFTTYB/hCIAiCt7VIlyHhO+uo0DOfxIC+gNVKoWyGd0xdQ3xSUmfdNvUigW7ZkUKDkAIBpRcmOLx5wV4y77I/4MghTl3FAZlhhFoBdAUKLZWpbISU8xfAUkI1s/md0mAztMTbqzkRT94AsSI1/KPnH7fuuH82ABJcp0UnKWh8aIlkbjD2vVCKXn9omMBEBRmTx68IuHoP4iT5mTyd6R3OfnEM6Vc6AZ9SLytjoP7Iu2hPKR7uqGJW/2KZ0jIZ4Hn+bJfl23fBexgJl4jK33aeIIkw/Og67w/CRK4MgiHtSLp7x1I3Fsmw8EYbQ2nZe3lA4SH1DU"); } catch (Exception ex) { LogManager.Log(ex, "Error settings SciChart runtime license."); } base.OnStartup(e); exceptionTrapper = new WpfGlobalExceptionTrapper(); exceptionTrapper.Initialize(this); exceptionTrapper.ApplicationCrashed += ExceptionTrapper_ApplicationCrashed; if (!Debugger.IsAttached) { ProcessLastApplicationTermination(); } } #region Global Exception Trapping private void ProcessLastApplicationTermination() { try { LogManager.Log("Analyzing previous application termination state..."); var settings = SettingsManager.Default.GetOrCreate(); if (!settings.TerminatedExpectedly) { GetLastApplicationCrashFromWindows(); } settings.TerminatedExpectedly = false; settings.Save(); } catch (Exception ex) { LogManager.Log(ex, "Error occurred while processing application last termination state."); } } private async void GetLastApplicationCrashFromWindows() { //Try find event log crash reports from the last 60 minutes... var logItem = await exceptionTrapper.GetLastApplicationCrashEventLog(60); if (logItem != null) { IsStartedAfterCrash = true; StartedAfterCrashError = logItem.Message; LogManager.Log(logItem); } } /// /// Handles the ApplicationCrashed event of the ExceptionTrapper. /// /// The source of the event. /// The instance containing the event data. private void ExceptionTrapper_ApplicationCrashed(object sender, ApplicationCrashedEventArgs e) { e.TryRecover = true; List ignoredExceptions = new List() { "FocusVisualStyle", "ThreadAbortException", "A Task's exception(s) were not observed", "The calling thread must be STA, because many UI components require this." }; String exceptionString = e.Exception.ToStringSafe(); if (ignoredExceptions.Exists(x => exceptionString.Contains(x))) { //TODO: Not sure why this damn exception is thrown sometimes when setting VM IsFree... trying to catch it maybe... if (exceptionString.Contains("The calling thread must be STA, because many UI components require this.")) { if (Debugger.IsAttached) { Debugger.Break(); } } return; } try { LogManager.Log(e.Exception, LogCategory.Critical, "Application Crashed!"); LogManager.Log("Trying to recover from application crash..."); try { if (Application.Current == null) { new Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; } } catch { } if (!_ignoredGlobalExceptions.Contains(e.Exception.ToString())) { _ignoredGlobalExceptions.Add(e.Exception.ToString()); Application.Current.Dispatcher.Invoke(() => { try { LogManager.Log("Trying to notify the user about the crash..."); INotificationProvider notificationProvider = TangoIOC.Default.GetInstance(); IBugReporter bugReporter = TangoIOC.Default.GetInstance(); if (notificationProvider != null) { if (e.Exception.GetType() == typeof(AuthorizationException)) { notificationProvider.PushSnackbarItem(MessageType.Error, "Authorization Error", true, "You are not authorized to perform the specified action.", TimeSpan.FromSeconds(8)); } else { notificationProvider.PushSnackbarItem(MessageType.Error, "Application Error", true, "Unexpected error has occurred\nTap to report this issue.", null, null, () => { if (bugReporter != null) { bugReporter.ShowBugReportDialog(new Bug() { Title = $"Unexpected Application Error", Description = e.Exception.Message, Type = BugType.FSE, Exception = e.Exception }); } }); } } } catch (Exception ex) { LogManager.Log(ex, "Error using the notification provider for notifying about application crash."); } }); } else { LogManager.Log("Global exception already presented to the user. Skipping user notification..."); } } catch (Exception ex) { LogManager.Log(ex, "Error in global exception trapper!"); } } #endregion } }