From 02f6e884d70269ce10dc016d740f07b99fbf495a Mon Sep 17 00:00:00 2001
From: Andy McFadden
Date: Sat, 20 Jul 2019 17:27:39 -0700
Subject: [PATCH] Fix startup issues
- MakeDist now copies CommonWPF.dll.
- Spent a bunch of time tracking down a null-pointer deref that only
happened when you didn't start with a config file. Fixed.
- The NPE was causing the program to exit without any sort of useful
diagnostic, so I added an uncaught exception handler that writes
the crash to a text file in the current directory.
- Added a trace listener definition to App.config that writes log
messages to a file, but it can't generally be enabled at runtime
because you can't write files from inside the sandbox. So it's
there but commented out.
- Made the initial size of the main window a little wider.
---
CommonUtil/Misc.cs | 36 +++++++++++++++++++++++
MakeDist/FileCopier.cs | 6 ++--
SourceGen/App.config | 12 ++++++++
SourceGen/RuntimeData/Help/tutorials.html | 4 +--
SourceGen/WpfGui/MainWindow.xaml | 2 +-
SourceGen/WpfGui/MainWindow.xaml.cs | 4 +++
SourceGen/WpfGui/NewProject.xaml.cs | 11 ++++---
7 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/CommonUtil/Misc.cs b/CommonUtil/Misc.cs
index 71625fe..d441a6a 100644
--- a/CommonUtil/Misc.cs
+++ b/CommonUtil/Misc.cs
@@ -14,6 +14,8 @@
* limitations under the License.
*/
using System;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
namespace CommonUtil {
@@ -28,5 +30,39 @@ namespace CommonUtil {
Console.WriteLine(" " + ns);
}
}
+
+ ///
+ /// Writes an unhandled exception trace to a crash file.
+ ///
+ ///
+ /// Usage:
+ /// AppDomain.CurrentDomain.UnhandledException +=
+ /// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);
+ ///
+ /// Thanks: https://stackoverflow.com/a/21308327/294248
+ ///
+ public static void CrashReporter(object sender, UnhandledExceptionEventArgs e) {
+ const string CRASH_PATH = @"CrashLog.txt";
+
+ Exception ex = (Exception)e.ExceptionObject;
+ Debug.WriteLine("CRASHING (term=" + e.IsTerminating + "): " + ex);
+
+ try {
+ using (StreamWriter writer = new StreamWriter(CRASH_PATH, true)) {
+ writer.WriteLine("*** " + DateTime.Now.ToLocalTime() + " ***");
+ while (ex != null) {
+ writer.WriteLine(ex.GetType().FullName + ": " + ex.Message);
+ writer.WriteLine("Trace:");
+ writer.WriteLine(ex.StackTrace);
+ writer.WriteLine(string.Empty);
+
+ ex = ex.InnerException;
+ }
+ }
+ } catch {
+ // damn it
+ Debug.WriteLine("Crashed while crashing");
+ }
+ }
}
}
diff --git a/MakeDist/FileCopier.cs b/MakeDist/FileCopier.cs
index f212a89..1a58264 100644
--- a/MakeDist/FileCopier.cs
+++ b/MakeDist/FileCopier.cs
@@ -62,8 +62,10 @@ namespace MakeDist {
SourceFileSpec.List, false, new string[] { "Asm65.dll" }),
new CopySpec("CommonUtil/bin/{BUILD_TYPE}/netstandard2.0/", ".",
SourceFileSpec.List, false, new string[] { "CommonUtil.dll" }),
- new CopySpec("CommonWinForms/bin/{BUILD_TYPE}/", ".",
- SourceFileSpec.List, false, new string[] { "CommonWinForms.dll" }),
+ //new CopySpec("CommonWinForms/bin/{BUILD_TYPE}/", ".",
+ // SourceFileSpec.List, false, new string[] { "CommonWinForms.dll" }),
+ new CopySpec("CommonWPF/bin/{BUILD_TYPE}/", ".",
+ SourceFileSpec.List, false, new string[] { "CommonWPF.dll" }),
new CopySpec("PluginCommon/bin/{BUILD_TYPE}/netstandard2.0/", ".",
SourceFileSpec.List, false, new string[] { "PluginCommon.dll" }),
new CopySpec("SourceGen/bin/{BUILD_TYPE}/", ".",
diff --git a/SourceGen/App.config b/SourceGen/App.config
index b50c74f..9e14e6c 100644
--- a/SourceGen/App.config
+++ b/SourceGen/App.config
@@ -3,4 +3,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/SourceGen/RuntimeData/Help/tutorials.html b/SourceGen/RuntimeData/Help/tutorials.html
index 4d51886..971e2eb 100644
--- a/SourceGen/RuntimeData/Help/tutorials.html
+++ b/SourceGen/RuntimeData/Help/tutorials.html
@@ -27,8 +27,8 @@ manual is recommended.
Start by launching SourceGen. The initial screen has a large
-center area with some links, and some mostly-empty windows on the sides.
-The links are shortcuts for menu items in the File menu.
+center area with some buttons, and some mostly-empty windows on the sides.
+The buttons are shortcuts for menu items in the File menu.
Create the project
diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml
index 6977586..3c06c27 100644
--- a/SourceGen/WpfGui/MainWindow.xaml
+++ b/SourceGen/WpfGui/MainWindow.xaml
@@ -23,7 +23,7 @@ limitations under the License.
mc:Ignorable="d"
Title="6502bench SourceGen"
Icon="/SourceGen;component/Res/SourceGenIcon.ico"
- Width="1000" Height="700" MinWidth="800" MinHeight="500"
+ Width="1200" Height="700" MinWidth="800" MinHeight="500"
SourceInitialized="Window_SourceInitialized"
Loaded="Window_Loaded"
LocationChanged="Window_LocationChanged"
diff --git a/SourceGen/WpfGui/MainWindow.xaml.cs b/SourceGen/WpfGui/MainWindow.xaml.cs
index 1bd8104..f8ab083 100644
--- a/SourceGen/WpfGui/MainWindow.xaml.cs
+++ b/SourceGen/WpfGui/MainWindow.xaml.cs
@@ -159,8 +159,12 @@ namespace SourceGen.WpfGui {
public MainWindow() {
+ Debug.WriteLine("START at " + DateTime.Now.ToLocalTime());
InitializeComponent();
+ AppDomain.CurrentDomain.UnhandledException +=
+ new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);
+
listViewSetSelectedItems = codeListView.GetType().GetMethod("SetSelectedItems",
BindingFlags.NonPublic | BindingFlags.Instance);
Debug.Assert(listViewSetSelectedItems != null);
diff --git a/SourceGen/WpfGui/NewProject.xaml.cs b/SourceGen/WpfGui/NewProject.xaml.cs
index d0a0905..627e913 100644
--- a/SourceGen/WpfGui/NewProject.xaml.cs
+++ b/SourceGen/WpfGui/NewProject.xaml.cs
@@ -57,8 +57,10 @@ namespace SourceGen.WpfGui {
"[nothing!selected]");
TreeViewItem selItem = PopulateNodes(prevSelSystem);
- selItem.IsSelected = true;
- selItem.BringIntoView();
+ if (selItem != null) {
+ selItem.IsSelected = true;
+ selItem.BringIntoView();
+ }
targetSystemTree.Focus();
@@ -70,7 +72,8 @@ namespace SourceGen.WpfGui {
///
/// TreeView to add items to
/// Name of previously-selected system.
- /// The node that matches prevSelSystem, or null if not found.
+ /// The node that matches prevSelSystem, or the first leaf node if no node
+ /// matches, or null if no leaf nodes are found.
private TreeViewItem PopulateNodes(string prevSelSystem) {
TreeViewItem selItem = null;
@@ -105,7 +108,7 @@ namespace SourceGen.WpfGui {
newItem.Tag = sd;
groupItem.Items.Add(newItem);
- if (isValid && sd.Name == prevSelSystem) {
+ if ((isValid && sd.Name == prevSelSystem) || selItem == null) {
selItem = newItem;
}
}