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.
This commit is contained in:
Andy McFadden 2019-07-20 17:27:39 -07:00
parent 06e28f89d1
commit 02f6e884d7
7 changed files with 66 additions and 9 deletions

View File

@ -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);
}
}
/// <summary>
/// Writes an unhandled exception trace to a crash file.
/// </summary>
/// <remarks>
/// Usage:
/// AppDomain.CurrentDomain.UnhandledException +=
/// new UnhandledExceptionEventHandler(CommonUtil.Misc.CrashReporter);
///
/// Thanks: https://stackoverflow.com/a/21308327/294248
/// </remarks>
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");
}
}
}
}

View File

@ -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}/", ".",

View File

@ -3,4 +3,16 @@
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<!-- https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/how-to-create-and-initialize-trace-listeners -->
<!-- WARNING: this will clash with the security sandbox -->
<!--<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="myListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="TextWriterOutput.log" />
</listeners>
</trace>
</system.diagnostics>-->
</configuration>

View File

@ -27,8 +27,8 @@ manual is recommended.</p>
<h2><a name="basic-features">Tutorial #1: Basic Features</a></h2>
<p>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.</p>
center area with some buttons, and some mostly-empty windows on the sides.
The buttons are shortcuts for menu items in the File menu.</p>
<h3>Create the project</h3>

View File

@ -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"

View File

@ -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);

View File

@ -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 {
/// </summary>
/// <param name="tv">TreeView to add items to</param>
/// <param name="prevSelSystem">Name of previously-selected system.</param>
/// <returns>The node that matches prevSelSystem, or null if not found.</returns>
/// <returns>The node that matches prevSelSystem, or the first leaf node if no node
/// matches, or null if no leaf nodes are found.</returns>
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;
}
}