Browse Source

Added some application state information to exception reports.

Currently reported values are: installed 3rd party addins, OpenSolution, CurrentProject, Workbench.ActiveContent.
More information can be added anywhere by registering a state getter with ICSharpCode.Core.ApplicationStateInfoService.RegisterStateGetter.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3455 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Christian Hornung 18 years ago
parent
commit
73bc1fcfbf
  1. 5
      src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs
  2. 7
      src/Main/Base/Project/Src/Project/Solution/Solution.cs
  3. 2
      src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
  4. 1
      src/Main/Core/Project/ICSharpCode.Core.csproj
  5. 20
      src/Main/Core/Project/Src/AddInTree/AddInTree.cs
  6. 159
      src/Main/Core/Project/Src/Services/ApplicationStateInfoService.cs
  7. 8
      src/Main/ICSharpCode.SharpDevelop.Sda/Src/ExceptionBox.cs

5
src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs

@ -19,6 +19,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -19,6 +19,7 @@ namespace ICSharpCode.SharpDevelop.Gui
const string uiIconStyle = "IconMenuItem.IconMenuStyle";
const string uiLanguageProperty = "CoreProperties.UILanguage";
const string workbenchMemento = "WorkbenchMemento";
const string activeContentState = "Workbench.ActiveContent";
static STAThreadCaller caller;
static IWorkbench workbench;
@ -115,6 +116,8 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -115,6 +116,8 @@ namespace ICSharpCode.SharpDevelop.Gui
workbench.SetMemento(PropertyService.Get(workbenchMemento, new Properties()));
workbench.WorkbenchLayout = layout;
ApplicationStateInfoService.RegisterStateGetter(activeContentState, delegate { return WorkbenchSingleton.Workbench.ActiveContent; });
OnWorkbenchCreated();
// initialize workbench-dependent services:
@ -141,6 +144,8 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -141,6 +144,8 @@ namespace ICSharpCode.SharpDevelop.Gui
Project.ProjectService.CloseSolution();
NavigationService.Unload();
ApplicationStateInfoService.UnregisterStateGetter(activeContentState);
if (WorkbenchUnloaded != null) {
WorkbenchUnloaded(null, EventArgs.Empty);
}

7
src/Main/Base/Project/Src/Project/Solution/Solution.cs

@ -1186,5 +1186,12 @@ namespace ICSharpCode.SharpDevelop.Project @@ -1186,5 +1186,12 @@ namespace ICSharpCode.SharpDevelop.Project
feedbackSink.Done(true);
}
#endregion
public override string ToString()
{
return "[Solution: FileName=" + (this.FileName ?? "<null>") +
", HasProjects=" + this.HasProjects.ToString(System.Globalization.CultureInfo.InvariantCulture) +
", ReadOnly=" + this.ReadOnly.ToString(System.Globalization.CultureInfo.InvariantCulture) + "]";
}
}
}

2
src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs

@ -64,6 +64,8 @@ namespace ICSharpCode.SharpDevelop.Project @@ -64,6 +64,8 @@ namespace ICSharpCode.SharpDevelop.Project
WorkbenchSingleton.Workbench.ActiveViewContentChanged += ActiveViewContentChanged;
FileService.FileRenamed += FileServiceFileRenamed;
FileService.FileRemoved += FileServiceFileRemoved;
ApplicationStateInfoService.RegisterStateGetter("ProjectService.OpenSolution", delegate { return OpenSolution; });
ApplicationStateInfoService.RegisterStateGetter("ProjectService.CurrentProject", delegate { return CurrentProject; });
}
}

1
src/Main/Core/Project/ICSharpCode.Core.csproj

@ -81,6 +81,7 @@ @@ -81,6 +81,7 @@
<Compile Include="Src\AddInTree\AddInTreeNode.cs" />
<Compile Include="Src\AddInTree\TreePathNotFoundException.cs" />
<Compile Include="Src\CoreException.cs" />
<Compile Include="Src\Services\ApplicationStateInfoService.cs" />
<Compile Include="Src\Services\FileUtility\FileNameEventHandler.cs" />
<Compile Include="Src\Services\FileUtility\FileUtility.cs" />
<Compile Include="Src\Services\FileUtility\FileUtility.Minimal.cs" />

20
src/Main/Core/Project/Src/AddInTree/AddInTree.cs

@ -36,6 +36,26 @@ namespace ICSharpCode.Core @@ -36,6 +36,26 @@ namespace ICSharpCode.Core
conditionEvaluators.Add("Compare", new CompareConditionEvaluator());
conditionEvaluators.Add("Ownerstate", new OwnerStateConditionEvaluator());
ApplicationStateInfoService.RegisterStateGetter("Installed 3rd party AddIns", GetInstalledThirdPartyAddInsListAsString);
}
static object GetInstalledThirdPartyAddInsListAsString()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (AddIn addIn in AddIns) {
if (!FileUtility.IsBaseDirectory(FileUtility.ApplicationRootPath, addIn.FileName)) {
if (sb.Length > 0) sb.Append(", ");
sb.Append("[");
sb.Append(addIn.Name);
sb.Append(", Enabled=");
sb.Append(addIn.Enabled);
sb.Append(", Action=");
sb.Append(addIn.Action.ToString());
sb.Append("]");
}
}
return sb.ToString();
}
/// <summary>

159
src/Main/Core/Project/Src/Services/ApplicationStateInfoService.cs

@ -0,0 +1,159 @@ @@ -0,0 +1,159 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ICSharpCode.Core
{
/// <summary>
/// This service is used to summarize important information
/// about the state of the application when an exception occurs.
/// </summary>
public static class ApplicationStateInfoService
{
static readonly Dictionary<string, StateGetter> stateGetters = new Dictionary<string, StateGetter>(StringComparer.InvariantCulture);
/// <summary>
/// Registers a new method to be invoked to get information about the current state of the application.
/// </summary>
/// <param name="title">The title of the new state entry.</param>
/// <param name="stateGetter">The method to be invoked to get the state value.</param>
/// <exception cref="ArgumentNullException">The <paramref name="title"/> is null.</exception>
/// <exception cref="ArgumentException">A state getter with the specified <paramref name="title"/> is already registered.</exception>
public static void RegisterStateGetter(string title, StateGetter stateGetter)
{
lock(stateGetters) {
stateGetters.Add(title, stateGetter);
}
}
/// <summary>
/// Determines whether a state getter with the specified title is already registered.
/// </summary>
/// <param name="title">The title to look for.</param>
/// <returns><c>true</c>, if a state getter with the specified title is already registered, otherwise <c>false</c>.</returns>
public static bool IsRegistered(string title)
{
lock(stateGetters) {
return stateGetters.ContainsKey(title);
}
}
/// <summary>
/// Unregisters a state getter.
/// </summary>
/// <param name="title">The title of the state entry to remove.</param>
/// <returns><c>true</c> if the specified title was found and removed, otherwise <c>false</c>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="title"/> is null.</exception>
public static bool UnregisterStateGetter(string title)
{
lock(stateGetters) {
return stateGetters.Remove(title);
}
}
/// <summary>
/// Gets a snapshot of the current application state information from all registered state getters.
/// </summary>
/// <returns>A dictionary with the titles and results of all registered state getters.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public static IDictionary<string, object> GetCurrentApplicationStateInfo()
{
Dictionary<string, object> state = new Dictionary<string, object>(stateGetters.Count, stateGetters.Comparer);
lock(stateGetters) {
foreach (KeyValuePair<string, StateGetter> entry in stateGetters) {
try {
state.Add(entry.Key, entry.Value());
} catch (Exception ex) {
state.Add(entry.Key, new StateGetterExceptionInfo(ex));
}
}
}
return state;
}
/// <summary>
/// Appends the current application state information from all registered state getters
/// to the specified <see cref="StringBuilder"/>.
/// </summary>
/// <param name="sb">The <see cref="StringBuilder"/> to append the state information to.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public static void AppendFormatted(StringBuilder sb)
{
IFormattable f;
Exception e;
StateGetterExceptionInfo exceptionInfo;
foreach (KeyValuePair<string, object> entry in GetCurrentApplicationStateInfo()) {
e = null;
sb.Append(entry.Key);
sb.Append(": ");
if (entry.Value == null) {
sb.AppendLine("<null>");
} else {
f = entry.Value as IFormattable;
if (f != null) {
try {
sb.AppendLine(f.ToString(null, CultureInfo.InvariantCulture));
} catch (Exception ex) {
sb.AppendLine("--> Exception thrown by IFormattable.ToString:");
e = ex;
}
} else {
exceptionInfo = entry.Value as StateGetterExceptionInfo;
if (exceptionInfo != null) {
sb.AppendLine("--> Exception thrown by the state getter:");
e = exceptionInfo.Exception;
} else {
try {
sb.AppendLine(entry.Value.ToString());
} catch (Exception ex) {
sb.AppendLine("--> Exception thrown by ToString:");
e = ex;
}
}
}
}
if (e != null) {
sb.AppendLine(e.ToString());
}
}
}
sealed class StateGetterExceptionInfo
{
readonly Exception exception;
internal StateGetterExceptionInfo(Exception exception)
{
if (exception == null)
throw new ArgumentNullException("exception");
this.exception = exception;
}
internal Exception Exception {
get { return exception; }
}
public override string ToString()
{
return "StateGetterExceptionInfo: " + this.exception.ToString();
}
}
}
/// <summary>
/// A delegate used to get information about the current state of the application.
/// </summary>
public delegate object StateGetter();
}

8
src/Main/ICSharpCode.SharpDevelop.Sda/Src/ExceptionBox.cs

@ -141,6 +141,14 @@ namespace ICSharpCode.SharpDevelop.Sda @@ -141,6 +141,14 @@ namespace ICSharpCode.SharpDevelop.Sda
sb.AppendLine("Failed to append recent log messages.");
sb.AppendLine(ex.ToString());
}
sb.AppendLine();
sb.AppendLine("---- Post-error application state information:");
try {
ApplicationStateInfoService.AppendFormatted(sb);
} catch (Exception ex) {
sb.AppendLine("Failed to append application state information.");
sb.AppendLine(ex.ToString());
}
return sb.ToString();
}

Loading…
Cancel
Save