From e9c118ad48fc4d57a12bdeedaf73e4b02bf1780f Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 10 Jan 2024 15:52:16 -0500 Subject: [PATCH 01/20] update --- .../Utilities/CrashReportTool.cs | 66 +++++++++++++++---- src/DynamoSandbox/DynamoCoreSetup.cs | 37 +++++++++++ src/DynamoSandbox/Program.cs | 1 + 3 files changed, 90 insertions(+), 14 deletions(-) diff --git a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs index 40f742d1a25..6a707221aa1 100644 --- a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs +++ b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs @@ -1,4 +1,5 @@ using Dynamo.Core; +using Dynamo.Logging; using Dynamo.Models; using Dynamo.ViewModels; using System; @@ -116,6 +117,7 @@ internal static string CreateMiniDumpFile(string outputDir = null) return outputFile; } } + return null; } @@ -176,11 +178,11 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } DynamoModel model = viewModel?.Model; + + string cerToolDir = !string.IsNullOrEmpty(model?.CERLocation) ? + model?.CERLocation : FindCERToolInInstallLocations(); - string cerToolDir = !string.IsNullOrEmpty(model.CERLocation) ? - model.CERLocation : FindCERToolInInstallLocations(); - - var cerToolPath = Path.Combine(cerToolDir, CERDllName); + var cerToolPath = !string.IsNullOrEmpty(cerToolDir) ? Path.Combine(cerToolDir, CERDllName) : string.Empty; if (string.IsNullOrEmpty(cerToolPath) || !File.Exists(cerToolPath)) { model?.Logger?.LogError($"The CER tool was not found at location {cerToolPath}"); @@ -199,18 +201,34 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash { string logFile = Path.Combine(cerDir.FullName, "DynamoLog.log"); - File.Copy(model.Logger.LogPath, logFile); - // might be usefull to dump all loaded Packages into - // the log at this point. - filesToSend.Add(logFile); + try + { + File.Copy(model.Logger.LogPath, logFile); + // might be usefull to dump all loaded Packages into + // the log at this point. + filesToSend.Add(logFile); + } + catch(Exception ex) + { + model?.Logger?.LogError($"Failed to send Log file due to the following error : {ex.Message}"); + } } if (args.SendSettingsFile && model != null) { string settingsFile = Path.Combine(cerDir.FullName, "DynamoSettings.xml"); - File.Copy(model.PathManager.PreferenceFilePath, settingsFile); - filesToSend.Add(settingsFile); + try + { + File.Copy(model.PathManager.PreferenceFilePath, settingsFile); + + filesToSend.Add(settingsFile); + + } + catch (Exception ex) + { + model?.Logger?.LogError($"Failed to send Settings file due to the following error : {ex.Message}"); + } } if (args.HasDetails()) @@ -222,7 +240,14 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash if (args.SendRecordedCommands && viewModel != null) { - filesToSend.Add(viewModel.DumpRecordedCommands()); + try + { + filesToSend.Add(viewModel.DumpRecordedCommands()); + } + catch (Exception ex) + { + model?.Logger?.LogError($"Failed to send Commands file due to the following error : {ex.Message}"); + } } string appConfig = ""; @@ -234,11 +259,24 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash $"session_start_count=\"0\" session_clean_close_count=\"0\" current_session_length=\"0\" />"; } - string dynName = viewModel?.Model.CurrentWorkspace.Name; + string dynName = model?.CurrentWorkspace.Name; - var miniDumpFilePath = CreateMiniDumpFile(cerDir.FullName); - var upiConfigFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "upiconfig.xml"); + var miniDumpFilePath = string.Empty; + try + { + miniDumpFilePath = CreateMiniDumpFile(cerDir.FullName); + } + catch (Exception ex) + { + model?.Logger?.LogError($"Failed to generate minidump file due to the following error : {ex.Message}"); + } + + if (string.IsNullOrEmpty(miniDumpFilePath)) + { + return false; + } + var upiConfigFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "upiconfig.xml"); using (var cerDLL = new CerDLL(cerToolPath)) { cerDLL.ToggleCER(true); diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index 71ff2ca5d8b..4c6c4f5188f 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Windows; +using System.Windows.Threading; using Dynamo.Applications; using Dynamo.Controls; using Dynamo.Core; @@ -58,6 +59,9 @@ public void RunApplication(Application app) { try { + Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + // This line validates if the WebView2 Runtime is installed in the computer before launching DynamoSandbox, // if is not we return and then exit Dynamo Sandbox if (!WebView2Utilities.ValidateWebView2RuntimeInstalled()) @@ -161,5 +165,38 @@ private void ASMPreloadFailureHandler(string failureMessage) { MessageBoxService.Show(failureMessage, "DynamoSandbox", MessageBoxButton.OK, MessageBoxImage.Warning); } + + private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + { + if (e.Handled) + { + return; + } + + e.Handled = true; + CrashGracefully(e.Exception); + } + + private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + var ex = e.ExceptionObject as Exception; + CrashGracefully(ex); + } + + private void CrashGracefully(Exception ex) + { + viewModel?.Model?.Logger?.LogError($"Unhandled exception {ex.Message}"); + + try + { + DynamoModel.IsCrashing = true; + Analytics.TrackException(ex, true); + CrashReportTool.ShowCrashErrorReportWindow(viewModel, new Dynamo.Core.CrashErrorReportArgs(ex)); + } + catch + { } + + viewModel?.Exit(false); // don't allow cancellation + } } } diff --git a/src/DynamoSandbox/Program.cs b/src/DynamoSandbox/Program.cs index 44c945ae835..08ecd248c15 100644 --- a/src/DynamoSandbox/Program.cs +++ b/src/DynamoSandbox/Program.cs @@ -4,6 +4,7 @@ using System.IO; using System.Reflection; using System.Windows; +using System.Windows.Threading; namespace DynamoSandbox { From 4c00439aefd12d812f668ebd67d5ed4f1dab2940 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 10 Jan 2024 15:55:04 -0500 Subject: [PATCH 02/20] Update CrashReportTool.cs --- src/DynamoCoreWpf/Utilities/CrashReportTool.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs index 6a707221aa1..8c87ce49523 100644 --- a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs +++ b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs @@ -210,7 +210,7 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } catch(Exception ex) { - model?.Logger?.LogError($"Failed to send Log file due to the following error : {ex.Message}"); + model?.Logger?.LogError($"Failed to send Log file to CER due to the following error : {ex.Message}"); } } @@ -227,7 +227,7 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } catch (Exception ex) { - model?.Logger?.LogError($"Failed to send Settings file due to the following error : {ex.Message}"); + model?.Logger?.LogError($"Failed to send Settings file to CER due to the following error : {ex.Message}"); } } @@ -246,7 +246,7 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } catch (Exception ex) { - model?.Logger?.LogError($"Failed to send Commands file due to the following error : {ex.Message}"); + model?.Logger?.LogError($"Failed to send Commands file to CER due to the following error : {ex.Message}"); } } @@ -268,7 +268,7 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } catch (Exception ex) { - model?.Logger?.LogError($"Failed to generate minidump file due to the following error : {ex.Message}"); + model?.Logger?.LogError($"Failed to generate minidump file for CER due to the following error : {ex.Message}"); } if (string.IsNullOrEmpty(miniDumpFilePath)) From f4f9ef1241f0c9cfcc5834364cd0b4b6ad1a2ef8 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 10 Jan 2024 15:56:50 -0500 Subject: [PATCH 03/20] Update DynamoCoreSetup.cs --- src/DynamoSandbox/DynamoCoreSetup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index 4c6c4f5188f..f5b54b86658 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -185,10 +185,10 @@ private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionE private void CrashGracefully(Exception ex) { - viewModel?.Model?.Logger?.LogError($"Unhandled exception {ex.Message}"); - try { + viewModel?.Model?.Logger?.LogError($"Unhandled exception {ex.Message}"); + DynamoModel.IsCrashing = true; Analytics.TrackException(ex, true); CrashReportTool.ShowCrashErrorReportWindow(viewModel, new Dynamo.Core.CrashErrorReportArgs(ex)); From 827f69f7f5605f6b1015e7e2432b723facc33162 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Mon, 22 Jan 2024 15:37:15 -0500 Subject: [PATCH 04/20] Update DynamoCoreSetup.cs --- src/DynamoSandbox/DynamoCoreSetup.cs | 95 ++++++++++++---------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index f5b54b86658..a5b6af161fb 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -86,51 +86,7 @@ public void RunApplication(Application app) } catch (Exception e) { - try - { -#if DEBUG - // Display the recorded command XML when the crash happens, - // so that it maybe saved and re-run later - if (viewModel != null) - viewModel.SaveRecordedCommand.Execute(null); -#endif - - DynamoModel.IsCrashing = true; - Analytics.TrackException(e, true); - - if (viewModel != null) - { - // Show the unhandled exception dialog so user can copy the - // crash details and report the crash if she chooses to. - viewModel.Model.OnRequestsCrashPrompt(new CrashErrorReportArgs(e)); - - // Give user a chance to save (but does not allow cancellation) - viewModel.Exit(allowCancel: false); - } - else - { - //show a message dialog box with the exception so the user - //can effectively report the issue. - var shortStackTrace = String.Join(Environment.NewLine, e.StackTrace.Split(Environment.NewLine.ToCharArray()).Take(10)); - - var result = MessageBoxService.Show(e.Message + - $" {Environment.NewLine} {e.InnerException?.Message} {Environment.NewLine} {shortStackTrace} {Environment.NewLine} " + - Environment.NewLine + string.Format(Resources.SandboxBuildsPageDialogMessage, sandboxWikiPage), - Resources.SandboxCrashMessage, MessageBoxButton.YesNo, MessageBoxImage.Error); - - if (result == MessageBoxResult.Yes) - { - Process.Start(new ProcessStartInfo(sandboxWikiPage) { UseShellExecute = true }); - } - } - } - catch - { - // Do nothing for now. - } - - Debug.WriteLine(e.Message); - Debug.WriteLine(e.StackTrace); + HandleException(e); } } @@ -174,29 +130,62 @@ private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhan } e.Handled = true; - CrashGracefully(e.Exception); + HandleException(e.Exception); } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var ex = e.ExceptionObject as Exception; - CrashGracefully(ex); + HandleException(ex); } - private void CrashGracefully(Exception ex) + private void HandleException(Exception e) { try { - viewModel?.Model?.Logger?.LogError($"Unhandled exception {ex.Message}"); +#if DEBUG + // Display the recorded command XML when the crash happens, + // so that it maybe saved and re-run later + if (viewModel != null) + viewModel.SaveRecordedCommand.Execute(null); +#endif DynamoModel.IsCrashing = true; - Analytics.TrackException(ex, true); - CrashReportTool.ShowCrashErrorReportWindow(viewModel, new Dynamo.Core.CrashErrorReportArgs(ex)); + Analytics.TrackException(e, true); + + if (viewModel != null) + { + // Show the unhandled exception dialog so user can copy the + // crash details and report the crash if she chooses to. + viewModel.Model.OnRequestsCrashPrompt(new CrashErrorReportArgs(e)); + + // Give user a chance to save (but does not allow cancellation) + viewModel.Exit(allowCancel: false); + } + else + { + //show a message dialog box with the exception so the user + //can effectively report the issue. + var shortStackTrace = String.Join(Environment.NewLine, e.StackTrace.Split(Environment.NewLine.ToCharArray()).Take(10)); + + var result = MessageBoxService.Show(e.Message + + $" {Environment.NewLine} {e.InnerException?.Message} {Environment.NewLine} {shortStackTrace} {Environment.NewLine} " + + Environment.NewLine + string.Format(Resources.SandboxBuildsPageDialogMessage, sandboxWikiPage), + Resources.SandboxCrashMessage, MessageBoxButton.YesNo, MessageBoxImage.Error); + + if (result == MessageBoxResult.Yes) + { + Process.Start(new ProcessStartInfo(sandboxWikiPage) { UseShellExecute = true }); + } + } } catch - { } + { + // Do nothing for now. + } - viewModel?.Exit(false); // don't allow cancellation + Debug.WriteLine(e.Message); + Debug.WriteLine(e.StackTrace); } } } From 50deee5c217b8ce6c752a944754e7aa5b09a7ca6 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 24 Jan 2024 11:26:24 -0500 Subject: [PATCH 05/20] Update DynamoCoreSetup.cs --- src/DynamoSandbox/DynamoCoreSetup.cs | 109 +++++++++++---------------- 1 file changed, 46 insertions(+), 63 deletions(-) diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index a5b6af161fb..dfc065a19ac 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -59,7 +59,6 @@ public void RunApplication(Application app) { try { - Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // This line validates if the WebView2 Runtime is installed in the computer before launching DynamoSandbox, @@ -86,7 +85,51 @@ public void RunApplication(Application app) } catch (Exception e) { - HandleException(e); + try + { +#if DEBUG + // Display the recorded command XML when the crash happens, + // so that it maybe saved and re-run later + if (viewModel != null) + viewModel.SaveRecordedCommand.Execute(null); +#endif + + DynamoModel.IsCrashing = true; + Analytics.TrackException(e, true); + + if (viewModel != null) + { + // Show the unhandled exception dialog so user can copy the + // crash details and report the crash if she chooses to. + viewModel.Model.OnRequestsCrashPrompt(new CrashErrorReportArgs(e)); + + // Give user a chance to save (but does not allow cancellation) + viewModel.Exit(allowCancel: false); + } + else + { + //show a message dialog box with the exception so the user + //can effectively report the issue. + var shortStackTrace = String.Join(Environment.NewLine, e.StackTrace.Split(Environment.NewLine.ToCharArray()).Take(10)); + + var result = MessageBoxService.Show(e.Message + + $" {Environment.NewLine} {e.InnerException?.Message} {Environment.NewLine} {shortStackTrace} {Environment.NewLine} " + + Environment.NewLine + string.Format(Resources.SandboxBuildsPageDialogMessage, sandboxWikiPage), + Resources.SandboxCrashMessage, MessageBoxButton.YesNo, MessageBoxImage.Error); + + if (result == MessageBoxResult.Yes) + { + Process.Start(new ProcessStartInfo(sandboxWikiPage) { UseShellExecute = true }); + } + } + } + catch + { + // Do nothing for now. + } + + Debug.WriteLine(e.Message); + Debug.WriteLine(e.StackTrace); } } @@ -122,70 +165,10 @@ private void ASMPreloadFailureHandler(string failureMessage) MessageBoxService.Show(failureMessage, "DynamoSandbox", MessageBoxButton.OK, MessageBoxImage.Warning); } - private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) - { - if (e.Handled) - { - return; - } - - e.Handled = true; - HandleException(e.Exception); - } - private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var ex = e.ExceptionObject as Exception; - HandleException(ex); - } - - private void HandleException(Exception e) - { - try - { -#if DEBUG - // Display the recorded command XML when the crash happens, - // so that it maybe saved and re-run later - if (viewModel != null) - viewModel.SaveRecordedCommand.Execute(null); -#endif - - DynamoModel.IsCrashing = true; - Analytics.TrackException(e, true); - - if (viewModel != null) - { - // Show the unhandled exception dialog so user can copy the - // crash details and report the crash if she chooses to. - viewModel.Model.OnRequestsCrashPrompt(new CrashErrorReportArgs(e)); - - // Give user a chance to save (but does not allow cancellation) - viewModel.Exit(allowCancel: false); - } - else - { - //show a message dialog box with the exception so the user - //can effectively report the issue. - var shortStackTrace = String.Join(Environment.NewLine, e.StackTrace.Split(Environment.NewLine.ToCharArray()).Take(10)); - - var result = MessageBoxService.Show(e.Message + - $" {Environment.NewLine} {e.InnerException?.Message} {Environment.NewLine} {shortStackTrace} {Environment.NewLine} " + - Environment.NewLine + string.Format(Resources.SandboxBuildsPageDialogMessage, sandboxWikiPage), - Resources.SandboxCrashMessage, MessageBoxButton.YesNo, MessageBoxImage.Error); - - if (result == MessageBoxResult.Yes) - { - Process.Start(new ProcessStartInfo(sandboxWikiPage) { UseShellExecute = true }); - } - } - } - catch - { - // Do nothing for now. - } - - Debug.WriteLine(e.Message); - Debug.WriteLine(e.StackTrace); + viewModel?.Model?.OnRequestsCrashPrompt(new CrashErrorReportArgs(ex)); } } } From 8baed4f9796af02ad0614200150224fb8082518a Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 24 Jan 2024 11:30:11 -0500 Subject: [PATCH 06/20] update --- src/DynamoSandbox/DynamoCoreSetup.cs | 1 - src/DynamoSandbox/Program.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index dfc065a19ac..1b19c21c214 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Runtime.InteropServices; using System.Windows; -using System.Windows.Threading; using Dynamo.Applications; using Dynamo.Controls; using Dynamo.Core; diff --git a/src/DynamoSandbox/Program.cs b/src/DynamoSandbox/Program.cs index 08ecd248c15..44c945ae835 100644 --- a/src/DynamoSandbox/Program.cs +++ b/src/DynamoSandbox/Program.cs @@ -4,7 +4,6 @@ using System.IO; using System.Reflection; using System.Windows; -using System.Windows.Threading; namespace DynamoSandbox { From b25cdf772c3723d7c705bf6b2c7b548e329b32bb Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 24 Jan 2024 11:34:48 -0500 Subject: [PATCH 07/20] Update CrashReportTool.cs --- src/DynamoCoreWpf/Utilities/CrashReportTool.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs index d2626149515..b2688b41a71 100644 --- a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs +++ b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs @@ -1,5 +1,4 @@ using Dynamo.Core; -using Dynamo.Logging; using Dynamo.Models; using Dynamo.ViewModels; using System; @@ -178,9 +177,6 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } DynamoModel model = viewModel?.Model; - - string cerToolDir = !string.IsNullOrEmpty(model?.CERLocation) ? - model?.CERLocation : FindCERToolInInstallLocations(); string cerToolDir = !string.IsNullOrEmpty(model?.CERLocation) ? model?.CERLocation : FindCERToolInInstallLocations(); @@ -285,6 +281,7 @@ internal static bool ShowCrashErrorReportWindow(DynamoViewModel viewModel, Crash } var upiConfigFilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "upiconfig.xml"); + using (var cerDLL = new CerDLL(cerToolPath)) { cerDLL.ToggleCER(true); From ca7dec4d1ccb2ecb80feb6dc08b485c268660525 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 31 Jan 2024 16:05:03 -0500 Subject: [PATCH 08/20] update --- src/DynamoCore/Models/DynamoModel.cs | 2 ++ .../ViewModels/Core/DynamoViewModel.cs | 26 ++++++++++++++++--- src/DynamoSandbox/DynamoCoreSetup.cs | 7 +++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs index 27713cb10e3..59049486ebc 100644 --- a/src/DynamoCore/Models/DynamoModel.cs +++ b/src/DynamoCore/Models/DynamoModel.cs @@ -614,6 +614,8 @@ public static DynamoModel Start(IStartConfiguration configuration) /// Start configuration protected DynamoModel(IStartConfiguration config) { + DynamoModel.IsCrashing = false; + if (config is DefaultStartConfiguration defaultStartConfig) { // This is not exposed in IStartConfiguration to avoid a breaking change. diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index a25503f6729..cba8ac4f30e 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Forms; @@ -691,6 +692,7 @@ public struct StartConfiguration protected DynamoViewModel(StartConfiguration startConfiguration) { Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; + TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; this.ShowLogin = startConfiguration.ShowLogin; @@ -772,13 +774,28 @@ protected DynamoViewModel(StartConfiguration startConfiguration) MLDataPipelineExtension = model.ExtensionManager.Extensions.OfType().FirstOrDefault(); } + + private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) + { + try + { + var crashData = new CrashErrorReportArgs(e.Exception); + Model?.Logger?.LogError($"Unobserved task exception: {crashData.Details}"); + Analytics.TrackException(e.Exception, true); + } + catch + { } + } + private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { - if (e.Handled) + if (e.Handled || DynamoModel.IsCrashing) { return; } + // Try to handle the exception so that the host app can continue in most cases. + // In some cases Dynamo code might still crash after this handler kicks in. In these edge cases we might see 2 CER windows (the extra one from the host app) e.Handled = true; CrashGracefully(e.Exception); } @@ -787,12 +804,12 @@ private void CrashGracefully(Exception ex) { try { - Model?.Logger?.LogError($"Unhandled exception {ex.Message}"); - DynamoModel.IsCrashing = true; + var crashData = new CrashErrorReportArgs(ex); + Model?.Logger?.LogError($"Unhandled exception: {crashData.Details} "); Analytics.TrackException(ex, true); - Model?.OnRequestsCrashPrompt(new CrashErrorReportArgs(ex)); + Model?.OnRequestsCrashPrompt(crashData); Exit(false); // don't allow cancellation } catch @@ -3491,6 +3508,7 @@ public ShutdownParams( public bool PerformShutdownSequence(ShutdownParams shutdownParams) { Dispatcher.CurrentDispatcher.UnhandledException -= CurrentDispatcher_UnhandledException; + TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException; if (shutdownSequenceInitiated) { diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index 2d836862090..bb9474fcb97 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -166,8 +166,11 @@ private void ASMPreloadFailureHandler(string failureMessage) private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - var ex = e.ExceptionObject as Exception; - viewModel?.Model?.OnRequestsCrashPrompt(new CrashErrorReportArgs(ex)); + if (!DynamoModel.IsCrashing)//Avoid duplicate CER reports + { + var ex = e.ExceptionObject as Exception; + viewModel?.Model?.OnRequestsCrashPrompt(new CrashErrorReportArgs(ex)); + } } } } From 9b82bebee1e39ef9e90fa1197dd721ef983bcf0d Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 31 Jan 2024 16:07:41 -0500 Subject: [PATCH 09/20] Update CrashReportTool.cs --- src/DynamoCoreWpf/Utilities/CrashReportTool.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs index b2688b41a71..a44e2062d67 100644 --- a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs +++ b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs @@ -116,7 +116,6 @@ internal static string CreateMiniDumpFile(string outputDir = null) return outputFile; } } - return null; } From ef66fb3f0959d3601b0152136afe38b54cebd37b Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 31 Jan 2024 16:10:56 -0500 Subject: [PATCH 10/20] update --- src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs | 2 +- src/DynamoSandbox/DynamoCoreSetup.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index cba8ac4f30e..411d31dc1f1 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -800,7 +800,7 @@ private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhan CrashGracefully(e.Exception); } - private void CrashGracefully(Exception ex) + internal void CrashGracefully(Exception ex) { try { diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index bb9474fcb97..51a3a18ba59 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -168,8 +168,7 @@ private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionE { if (!DynamoModel.IsCrashing)//Avoid duplicate CER reports { - var ex = e.ExceptionObject as Exception; - viewModel?.Model?.OnRequestsCrashPrompt(new CrashErrorReportArgs(ex)); + viewModel?.CrashGracefully(e.ExceptionObject as Exception); } } } From bebb02e72a2aac05d906abe9a457ac707a7ba136 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 31 Jan 2024 16:47:28 -0500 Subject: [PATCH 11/20] Update CerDLL.cs --- src/DynamoCoreWpf/Utilities/CerDLL.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DynamoCoreWpf/Utilities/CerDLL.cs b/src/DynamoCoreWpf/Utilities/CerDLL.cs index c0302e0dd65..3040de77c76 100644 --- a/src/DynamoCoreWpf/Utilities/CerDLL.cs +++ b/src/DynamoCoreWpf/Utilities/CerDLL.cs @@ -33,6 +33,7 @@ public void Dispose() DLL.FreeLibrary(m_dll); m_dll = IntPtr.Zero; } + Initialized = false; } private static bool Initialized; From a3990d6e8b267b43059cdc6e3ccc4904cb3e75b6 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Thu, 1 Feb 2024 11:14:20 -0500 Subject: [PATCH 12/20] Update DynamoView.xaml.cs --- src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs index c2eac9f32c3..b393289bab4 100644 --- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs +++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs @@ -121,6 +121,7 @@ internal PreferencesView PreferencesWindow { /// Dynamo view model public DynamoView(DynamoViewModel dynamoViewModel) { + dynamoViewModel.Model.RequestsCrashPrompt += Controller_RequestsCrashPrompt; // The user's choice to enable hardware acceleration is now saved in // the Dynamo preferences. It is set to true by default. // When the view is constructed, we enable or disable hardware acceleration based on that preference. @@ -1335,7 +1336,6 @@ private void DynamoView_Loaded(object sender, EventArgs e) dynamoViewModel.RequestSave3DImage += DynamoViewModelRequestSave3DImage; dynamoViewModel.SidebarClosed += DynamoViewModelSidebarClosed; - dynamoViewModel.Model.RequestsCrashPrompt += Controller_RequestsCrashPrompt; dynamoViewModel.Model.RequestTaskDialog += Controller_RequestTaskDialog; DynamoSelection.Instance.Selection.CollectionChanged += Selection_CollectionChanged; From 5e075cf5aa3bdf0ff458f523554b2ddd7756557b Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Thu, 1 Feb 2024 15:41:33 -0500 Subject: [PATCH 13/20] Update DynamoViewModel.cs --- src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 411d31dc1f1..7e87912c6ec 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -797,7 +797,9 @@ private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhan // Try to handle the exception so that the host app can continue in most cases. // In some cases Dynamo code might still crash after this handler kicks in. In these edge cases we might see 2 CER windows (the extra one from the host app) e.Handled = true; + CrashGracefully(e.Exception); + } internal void CrashGracefully(Exception ex) @@ -810,7 +812,7 @@ internal void CrashGracefully(Exception ex) Analytics.TrackException(ex, true); Model?.OnRequestsCrashPrompt(crashData); - Exit(false); // don't allow cancellation + UIDispatcher?.BeginInvoke(() => Exit(false), DispatcherPriority.Send); } catch { } From bdff3b19a09ed4a86ef009d1f8d3a58946b0ca61 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Fri, 2 Feb 2024 09:44:01 -0500 Subject: [PATCH 14/20] update --- .../ViewModels/Core/DynamoViewModel.cs | 44 ++++++++++++++++--- src/DynamoSandbox/DynamoCoreSetup.cs | 11 ----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 7e87912c6ec..7d4074144da 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -691,6 +691,7 @@ public struct StartConfiguration protected DynamoViewModel(StartConfiguration startConfiguration) { + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; @@ -799,10 +800,17 @@ private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhan e.Handled = true; CrashGracefully(e.Exception); - } - internal void CrashGracefully(Exception ex) + private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + if (!DynamoModel.IsCrashing)//Avoid duplicate CER reports + { + CrashGracefully(e.ExceptionObject as Exception, fatal: true); + } + } + + internal void CrashGracefully(Exception ex, bool fatal = false) { try { @@ -810,9 +818,31 @@ internal void CrashGracefully(Exception ex) var crashData = new CrashErrorReportArgs(ex); Model?.Logger?.LogError($"Unhandled exception: {crashData.Details} "); Analytics.TrackException(ex, true); - Model?.OnRequestsCrashPrompt(crashData); - UIDispatcher?.BeginInvoke(() => Exit(false), DispatcherPriority.Send); + + if (fatal) + { + UIDispatcher?.Invoke(() => { + try + { + Exit(false); + } + catch { } + }, DispatcherPriority.Send); + + Environment.Exit(1); + } + else + { + UIDispatcher?.BeginInvoke(() => { + try + { + Exit(false); + } + catch + { } + }, DispatcherPriority.Send); + } } catch { } @@ -3509,9 +3539,6 @@ public ShutdownParams( /// public bool PerformShutdownSequence(ShutdownParams shutdownParams) { - Dispatcher.CurrentDispatcher.UnhandledException -= CurrentDispatcher_UnhandledException; - TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException; - if (shutdownSequenceInitiated) { // There was a prior call to shutdown. This could happen for example @@ -3548,6 +3575,9 @@ public bool PerformShutdownSequence(ShutdownParams shutdownParams) model.ShutDown(shutdownParams.ShutdownHost); UsageReportingManager.DestroyInstance(); + + Dispatcher.CurrentDispatcher.UnhandledException -= CurrentDispatcher_UnhandledException; + TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException; this.model.CommandStarting -= OnModelCommandStarting; this.model.CommandCompleted -= OnModelCommandCompleted; BackgroundPreviewViewModel.PropertyChanged -= Watch3DViewModelPropertyChanged; diff --git a/src/DynamoSandbox/DynamoCoreSetup.cs b/src/DynamoSandbox/DynamoCoreSetup.cs index 51a3a18ba59..6964f03c000 100644 --- a/src/DynamoSandbox/DynamoCoreSetup.cs +++ b/src/DynamoSandbox/DynamoCoreSetup.cs @@ -10,7 +10,6 @@ using Dynamo.Logging; using Dynamo.Models; using Dynamo.ViewModels; -using Dynamo.Wpf.UI; using Dynamo.Wpf.Utilities; using Dynamo.Wpf.ViewModels.Watch3D; @@ -58,8 +57,6 @@ public void RunApplication(Application app) { try { - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - // This line validates if the WebView2 Runtime is installed in the computer before launching DynamoSandbox, // if is not we return and then exit Dynamo Sandbox if (!WebView2Utilities.ValidateWebView2RuntimeInstalled()) @@ -163,13 +160,5 @@ private void ASMPreloadFailureHandler(string failureMessage) { MessageBoxService.Show(failureMessage, "DynamoSandbox", MessageBoxButton.OK, MessageBoxImage.Warning); } - - private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - if (!DynamoModel.IsCrashing)//Avoid duplicate CER reports - { - viewModel?.CrashGracefully(e.ExceptionObject as Exception); - } - } } } From f15f8919c6b9551654ea4d9b922adf992872a73e Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Fri, 2 Feb 2024 09:51:30 -0500 Subject: [PATCH 15/20] Update DynamoViewModel.cs --- .../ViewModels/Core/DynamoViewModel.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 7d4074144da..9a8754cb0cf 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -795,8 +795,9 @@ private void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhan return; } - // Try to handle the exception so that the host app can continue in most cases. - // In some cases Dynamo code might still crash after this handler kicks in. In these edge cases we might see 2 CER windows (the extra one from the host app) + // Try to handle the exception so that the host app can continue (in most cases). + // In some cases Dynamo code might still crash after this handler kicks in. In these edge cases + // we might see 2 CER windows (the extra one from the host app) - CER tool might handle this in the future. e.Handled = true; CrashGracefully(e.Exception); @@ -822,6 +823,9 @@ internal void CrashGracefully(Exception ex, bool fatal = false) if (fatal) { + // Fatal exception. Close Dynamo and terminate the process. + + // Run the Dynamo exit code in the UI thread since CrashGracefully could be called in other threads too. UIDispatcher?.Invoke(() => { try { @@ -829,11 +833,17 @@ internal void CrashGracefully(Exception ex, bool fatal = false) } catch { } }, DispatcherPriority.Send); - + + // We terminate the process here so that no other exceptions can leak to the host apps. + // All fatal exceptions will result in a process termination (either by Dynamo, host app or CLR) Environment.Exit(1); } else { + // Non fatal exception. + + // We run the Dynamo exit call asyncronously in the dispatcher to ensure that any continuation of code + // manages to run to completion before we start shutting down Dynamo. UIDispatcher?.BeginInvoke(() => { try { From 36dd65c41f5f01a959387741d56ab70c4b007195 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Fri, 2 Feb 2024 14:29:22 -0500 Subject: [PATCH 16/20] update --- .../ViewModels/Core/DynamoViewModel.cs | 36 +++++++++++++------ .../Views/Core/DynamoView.xaml.cs | 15 -------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 9a8754cb0cf..a46dc91ea4e 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -701,6 +701,7 @@ protected DynamoViewModel(StartConfiguration startConfiguration) this.model = startConfiguration.DynamoModel; this.model.CommandStarting += OnModelCommandStarting; this.model.CommandCompleted += OnModelCommandCompleted; + this.model.RequestsCrashPrompt += Controller_RequestsCrashPrompt; this.HideReportOptions = startConfiguration.HideReportOptions; UsageReportingManager.Instance.InitializeCore(this); @@ -775,6 +776,18 @@ protected DynamoViewModel(StartConfiguration startConfiguration) MLDataPipelineExtension = model.ExtensionManager.Extensions.OfType().FirstOrDefault(); } + private void Controller_RequestsCrashPrompt(object sender, CrashPromptArgs args) + { + if (CrashReportTool.ShowCrashErrorReportWindow(this, + (args is CrashErrorReportArgs cerArgs) ? cerArgs : + new CrashErrorReportArgs(args.Details))) + { + return; + } + // Backup crash reporting dialog (in case ADSK CER is not found) + var prompt = new Nodes.Prompts.CrashPrompt(args, this); + prompt.ShowDialog(); + } private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { @@ -826,17 +839,18 @@ internal void CrashGracefully(Exception ex, bool fatal = false) // Fatal exception. Close Dynamo and terminate the process. // Run the Dynamo exit code in the UI thread since CrashGracefully could be called in other threads too. - UIDispatcher?.Invoke(() => { + TryDispatcherInvoke(() => { try { Exit(false); } catch { } - }, DispatcherPriority.Send); + }); - // We terminate the process here so that no other exceptions can leak to the host apps. - // All fatal exceptions will result in a process termination (either by Dynamo, host app or CLR) - Environment.Exit(1); + // Do not terminate the process in the plugin, because other AppDomain.UnhandledException events will not get a chance to get called + // ex. A host app (like Revit) could have an AppDomain.UnhandledException too. + // If we terminate the process here, the host app will not get a chance to gracefully shut down. + // Environment.Exit(1); } else { @@ -844,14 +858,14 @@ internal void CrashGracefully(Exception ex, bool fatal = false) // We run the Dynamo exit call asyncronously in the dispatcher to ensure that any continuation of code // manages to run to completion before we start shutting down Dynamo. - UIDispatcher?.BeginInvoke(() => { + TryDispatcherBeginInvoke(() => { try { Exit(false); } catch { } - }, DispatcherPriority.Send); + }); } } catch @@ -3568,6 +3582,11 @@ public bool PerformShutdownSequence(ShutdownParams shutdownParams) // that the shutdown may not be stopped. shutdownSequenceInitiated = true; + AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException; + Dispatcher.CurrentDispatcher.UnhandledException -= CurrentDispatcher_UnhandledException; + TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException; + this.Model.RequestsCrashPrompt -= Controller_RequestsCrashPrompt; + // Request the View layer to close its window (see // ShutdownParams.CloseDynamoView member for details). if (shutdownParams.CloseDynamoView) @@ -3575,7 +3594,6 @@ public bool PerformShutdownSequence(ShutdownParams shutdownParams) OnRequestClose(this, EventArgs.Empty); } - BackgroundPreviewViewModel.Dispose(); foreach (var wsvm in workspaces) { @@ -3586,8 +3604,6 @@ public bool PerformShutdownSequence(ShutdownParams shutdownParams) model.ShutDown(shutdownParams.ShutdownHost); UsageReportingManager.DestroyInstance(); - Dispatcher.CurrentDispatcher.UnhandledException -= CurrentDispatcher_UnhandledException; - TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException; this.model.CommandStarting -= OnModelCommandStarting; this.model.CommandCompleted -= OnModelCommandCompleted; BackgroundPreviewViewModel.PropertyChanged -= Watch3DViewModelPropertyChanged; diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs index b393289bab4..cc6ce0bd721 100644 --- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs +++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs @@ -121,7 +121,6 @@ internal PreferencesView PreferencesWindow { /// Dynamo view model public DynamoView(DynamoViewModel dynamoViewModel) { - dynamoViewModel.Model.RequestsCrashPrompt += Controller_RequestsCrashPrompt; // The user's choice to enable hardware acceleration is now saved in // the Dynamo preferences. It is set to true by default. // When the view is constructed, we enable or disable hardware acceleration based on that preference. @@ -1606,19 +1605,6 @@ private void Selection_CollectionChanged(object sender, NotifyCollectionChangedE dynamoViewModel.NodeFromSelectionCommand.RaiseCanExecuteChanged(); } - private void Controller_RequestsCrashPrompt(object sender, CrashPromptArgs args) - { - if (CrashReportTool.ShowCrashErrorReportWindow(dynamoViewModel, - (args is CrashErrorReportArgs cerArgs) ? cerArgs : - new CrashErrorReportArgs(args.Details))) - { - return; - } - // Backup crash reporting dialog (in case ADSK CER is not found) - var prompt = new CrashPrompt(args, dynamoViewModel); - prompt.ShowDialog(); - } - private void Controller_RequestTaskDialog(object sender, TaskDialogEventArgs e) { var taskDialog = new UI.Prompts.GenericTaskDialog(e); @@ -1982,7 +1968,6 @@ private void WindowClosed(object sender, EventArgs e) if (dynamoViewModel.Model != null) { - dynamoViewModel.Model.RequestsCrashPrompt -= Controller_RequestsCrashPrompt; dynamoViewModel.Model.RequestTaskDialog -= Controller_RequestTaskDialog; dynamoViewModel.Model.ClipBoard.CollectionChanged -= ClipBoard_CollectionChanged; } From ea9e968ecf72b2680b4ec7b4f4283b68c90fcf76 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Mon, 5 Feb 2024 09:58:49 -0500 Subject: [PATCH 17/20] update --- .../UI/Prompts/CrashPrompt.xaml.cs | 4 ++-- .../Utilities/CrashReportTool.cs | 15 +++++++++++++++ .../ViewModels/Core/DynamoViewModel.cs | 19 +++---------------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/DynamoCoreWpf/UI/Prompts/CrashPrompt.xaml.cs b/src/DynamoCoreWpf/UI/Prompts/CrashPrompt.xaml.cs index 22e762b4eb5..f2e392b13e2 100644 --- a/src/DynamoCoreWpf/UI/Prompts/CrashPrompt.xaml.cs +++ b/src/DynamoCoreWpf/UI/Prompts/CrashPrompt.xaml.cs @@ -51,10 +51,10 @@ public CrashPrompt(CrashPromptArgs args, DynamoViewModel dynamoViewModel) { InitializeComponent(); - var packageLoader = dynamoViewModel.Model.GetPackageManagerExtension()?.PackageLoader; + var packageLoader = dynamoViewModel?.Model?.GetPackageManagerExtension()?.PackageLoader; markdownPackages = Wpf.Utilities.CrashUtilities.PackagesToMakrdown(packageLoader); - productName = dynamoViewModel.BrandingResourceProvider.ProductName; + productName = dynamoViewModel?.BrandingResourceProvider.ProductName ?? Process.GetCurrentProcess().ProcessName; Title = string.Format(Wpf.Properties.Resources.CrashPromptDialogTitle, productName); TitleTextBlock.Text = string.Format(Wpf.Properties.Resources.CrashPromptDialogTitle, productName); txtOverridingText.Text = string.Format(Wpf.Properties.Resources.CrashPromptDialogCrashMessage, productName); diff --git a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs index a44e2062d67..305a0300d3e 100644 --- a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs +++ b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs @@ -162,6 +162,21 @@ private static string FindCERToolInInstallLocations() } } + internal static void ShowCrashWindow(object sender, CrashPromptArgs args) + { + var viewModel = sender as DynamoViewModel + ; + if (CrashReportTool.ShowCrashErrorReportWindow(viewModel, + (args is CrashErrorReportArgs cerArgs) ? cerArgs : + new CrashErrorReportArgs(args.Details))) + { + return; + } + // Backup crash reporting dialog (in case ADSK CER is not found) + var prompt = new Nodes.Prompts.CrashPrompt(args, viewModel); + prompt.ShowDialog(); + } + /// /// Calls external CER tool (with UI) /// diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index a46dc91ea4e..34e5ae31496 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -701,7 +701,7 @@ protected DynamoViewModel(StartConfiguration startConfiguration) this.model = startConfiguration.DynamoModel; this.model.CommandStarting += OnModelCommandStarting; this.model.CommandCompleted += OnModelCommandCompleted; - this.model.RequestsCrashPrompt += Controller_RequestsCrashPrompt; + this.model.RequestsCrashPrompt += CrashReportTool.ShowCrashWindow; this.HideReportOptions = startConfiguration.HideReportOptions; UsageReportingManager.Instance.InitializeCore(this); @@ -776,19 +776,6 @@ protected DynamoViewModel(StartConfiguration startConfiguration) MLDataPipelineExtension = model.ExtensionManager.Extensions.OfType().FirstOrDefault(); } - private void Controller_RequestsCrashPrompt(object sender, CrashPromptArgs args) - { - if (CrashReportTool.ShowCrashErrorReportWindow(this, - (args is CrashErrorReportArgs cerArgs) ? cerArgs : - new CrashErrorReportArgs(args.Details))) - { - return; - } - // Backup crash reporting dialog (in case ADSK CER is not found) - var prompt = new Nodes.Prompts.CrashPrompt(args, this); - prompt.ShowDialog(); - } - private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { try @@ -824,7 +811,7 @@ private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionE } } - internal void CrashGracefully(Exception ex, bool fatal = false) + private void CrashGracefully(Exception ex, bool fatal = false) { try { @@ -3585,7 +3572,7 @@ public bool PerformShutdownSequence(ShutdownParams shutdownParams) AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException; Dispatcher.CurrentDispatcher.UnhandledException -= CurrentDispatcher_UnhandledException; TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException; - this.Model.RequestsCrashPrompt -= Controller_RequestsCrashPrompt; + this.Model.RequestsCrashPrompt -= CrashReportTool.ShowCrashWindow; // Request the View layer to close its window (see // ShutdownParams.CloseDynamoView member for details). From 890672aa50ddd376d7d6cd52fa7438ccce9be3db Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Mon, 5 Feb 2024 15:53:07 -0500 Subject: [PATCH 18/20] update --- src/DynamoCoreWpf/Utilities/CrashReportTool.cs | 4 ++-- src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs index 305a0300d3e..37d1b44bf2c 100644 --- a/src/DynamoCoreWpf/Utilities/CrashReportTool.cs +++ b/src/DynamoCoreWpf/Utilities/CrashReportTool.cs @@ -164,8 +164,8 @@ private static string FindCERToolInInstallLocations() internal static void ShowCrashWindow(object sender, CrashPromptArgs args) { - var viewModel = sender as DynamoViewModel - ; + var viewModel = sender as DynamoViewModel; + if (CrashReportTool.ShowCrashErrorReportWindow(viewModel, (args is CrashErrorReportArgs cerArgs) ? cerArgs : new CrashErrorReportArgs(args.Details))) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 34e5ae31496..0d6532d1d18 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -823,7 +823,7 @@ private void CrashGracefully(Exception ex, bool fatal = false) if (fatal) { - // Fatal exception. Close Dynamo and terminate the process. + // Fatal exception. Close Dynamo but do not terminate the process. // Run the Dynamo exit code in the UI thread since CrashGracefully could be called in other threads too. TryDispatcherInvoke(() => { From 8d864f2b678fffd4a3b32a2b937b1a232ecb46b3 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Tue, 6 Feb 2024 12:52:17 -0500 Subject: [PATCH 19/20] Update SplashScreen.xaml.cs --- .../Views/SplashScreen/SplashScreen.xaml.cs | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs index fa8e470d772..cc3e530b892 100644 --- a/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs +++ b/src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs @@ -187,15 +187,30 @@ private void DynamoModel_LanguageDetected() } private void WebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) - { - if (webView != null) + { + try + { + // Exceptions thrown in WebView_NavigationCompleted seem to be silenced somewhere in the webview2 callstack. + // If we catch an exceptions here, we log it and close the spash screen. + // + if (webView != null) + { + webView.NavigationCompleted -= WebView_NavigationCompleted; + webView.Focus(); + System.Windows.Forms.SendKeys.SendWait("{TAB}"); + } + OnRequestDynamicSplashScreen(); + } + catch (Exception ex) { - webView.NavigationCompleted -= WebView_NavigationCompleted; - webView.Focus(); - System.Windows.Forms.SendKeys.SendWait("{TAB}"); + if (!DynamoModel.IsCrashing && !IsClosing) + { + CrashReportTool.ShowCrashWindow(viewModel, new CrashErrorReportArgs(ex)); + Close();// Close the SpashScreen + } } - OnRequestDynamicSplashScreen(); } + /// /// Request to close SplashScreen. /// From 6799a8c472e4042b7ee054895ce389cff63ee9ec Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 7 Feb 2024 12:13:59 -0500 Subject: [PATCH 20/20] Update DynamoViewModel.cs --- src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs index 0d6532d1d18..0becc9ac897 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs @@ -691,8 +691,11 @@ public struct StartConfiguration protected DynamoViewModel(StartConfiguration startConfiguration) { + // CurrentDomain_UnhandledException - catches unhandled exceptions that are fatal to the current process. These exceptions cannot be handled and process termination is guaranteed AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + // Dispatcher.CurrentDispatcher.UnhandledException - catches unhandled exceptions from the UI thread. Can mark exceptions as handled (and close Dynamo) so that host apps can continue running normally even though Dynamo crashed Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; + // TaskScheduler.UnobservedTaskException - catches unobserved Task exceptions from all threads. Does not crash Dynamo, we only log the exceptions and do not call CER or close Dynamo TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; this.ShowLogin = startConfiguration.ShowLogin;