Skip to content

Commit 0324273

Browse files
committed
Merge branch 'PolarGoose-main'
2 parents 56bdeb2 + ffd7849 commit 0324273

File tree

8 files changed

+139
-138
lines changed

8 files changed

+139
-138
lines changed

src/ExceptionVisualizer/ExceptionDebuggerVisualizerProvider.cs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,14 @@ namespace ExceptionVisualizer
88
/// <summary>
99
/// Debugger visualizer provider class for <see cref="System.String"/>.
1010
/// </summary>
11+
/// <remarks>
12+
/// Initializes a new instance of the <see cref="ExceptionDebuggerVisualizerProvider"/> class.
13+
/// </remarks>
14+
/// <param name="extension">Extension instance.</param>
15+
/// <param name="extensibility">Extensibility object.</param>
1116
[VisualStudioContribution]
12-
internal class ExceptionDebuggerVisualizerProvider : DebuggerVisualizerProvider
17+
internal class ExceptionDebuggerVisualizerProvider(ExtensionEntrypoint extension, VisualStudioExtensibility extensibility) : DebuggerVisualizerProvider(extension, extensibility)
1318
{
14-
/// <summary>
15-
/// Initializes a new instance of the <see cref="ExceptionDebuggerVisualizerProvider"/> class.
16-
/// </summary>
17-
/// <param name="extension">Extension instance.</param>
18-
/// <param name="extensibility">Extensibility object.</param>
19-
public ExceptionDebuggerVisualizerProvider(ExtensionEntrypoint extension, VisualStudioExtensibility extensibility)
20-
: base(extension, extensibility)
21-
{
22-
}
2319

2420
/// <inheritdoc/>
2521
public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Exception Visualizer", typeof(Exception))
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using ExceptionVisualizer.Models;
2+
using ExceptionVisualizerSource;
3+
using System.Collections.ObjectModel;
4+
using System.Windows;
5+
6+
namespace ExceptionVisualizer
7+
{
8+
internal static class ExceptionModelExtensions
9+
{
10+
internal static ExceptionViewModel ToViewModel(this ExceptionModel exception)
11+
{
12+
var viewModel = new ExceptionViewModel
13+
{
14+
Data = new ObservableCollection<DataViewModel>(exception.Data.Select(d => new DataViewModel
15+
{
16+
Key = d.Key,
17+
Value = d.Value,
18+
})),
19+
Properties = new ObservableCollection<DataViewModel>(exception.Properties.Select(d => new DataViewModel
20+
{
21+
Key = d.Key,
22+
Value = d.Value,
23+
})),
24+
ShowData = exception.Data.Count > 0 ? Visibility.Visible : Visibility.Collapsed,
25+
ShowProperties = exception.Properties.Count > 0 ? Visibility.Visible : Visibility.Collapsed,
26+
HelpLink = exception.HelpLink,
27+
HResult = exception.HResult,
28+
Message = exception.Message,
29+
Source = exception.Source,
30+
StackTrace = exception.StackTrace,
31+
TargetSite = exception.TargetSite,
32+
Demystified = exception.Demystified,
33+
@Type = exception.Type,
34+
};
35+
foreach (var inner in exception.InnerExceptions)
36+
{
37+
viewModel.InnerExceptions.Add(ToViewModel(inner));
38+
}
39+
40+
return viewModel;
41+
}
42+
}
43+
}
Lines changed: 64 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,64 @@
1-
using ExceptionVisualizer.Models;
2-
using ExceptionVisualizerSource;
3-
using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers;
4-
using Microsoft.VisualStudio.Extensibility.UI;
5-
using System.Collections.ObjectModel;
6-
using System.Windows;
7-
8-
namespace ExceptionVisualizer
9-
{
10-
internal class ExceptionUserControl : RemoteUserControl
11-
{
12-
private readonly VisualizerTarget visualizerTarget;
13-
14-
public ExceptionUserControl(VisualizerTarget visualizerTarget) : base(new ViewModel())
15-
{
16-
this.visualizerTarget = visualizerTarget;
17-
}
18-
19-
private ViewModel ViewModel => (ViewModel)this.DataContext!;
20-
21-
22-
public override Task ControlLoadedAsync(CancellationToken cancellationToken)
23-
{
24-
_ = Task.Run(async () =>
25-
{
26-
try
27-
{
28-
ExceptionModel? exception = await this.visualizerTarget.ObjectSource.RequestDataAsync<ExceptionModel?>(jsonSerializer: null, CancellationToken.None);
29-
if (exception != null)
30-
{
31-
var viewModel = ToViewModel(exception);
32-
ViewModel.Exceptions.Add(viewModel);
33-
Subscribe(viewModel);
34-
viewModel.IsSelected = true;
35-
}
36-
}
37-
catch (StreamJsonRpc.RemoteInvocationException rie) when (rie.Message.Contains("Could not load file or assembly 'Newtonsoft.Json"))
38-
{
39-
MessageBox.Show("There's currently a bug in Visual Studio causing the Exception Visualizer extension to crash when debugging projects containing a reference to Newtonsoft.Json older than version 13. Either upgrade to version 13 of Newtonsoft.Json or follow this issue on GitHub: https://github.com/microsoft/VSExtensibility/issues/248.");
40-
}
41-
catch (Exception ex)
42-
{
43-
Telemetry.TrackException(ex);
44-
}
45-
});
46-
return Task.CompletedTask;
47-
}
48-
49-
private void Subscribe(ExceptionViewModel model)
50-
{
51-
model.PropertyChanged += Exception_PropertyChanged;
52-
foreach (var inner in model.InnerExceptions)
53-
{
54-
Subscribe(inner);
55-
}
56-
}
57-
58-
private ExceptionViewModel ToViewModel(ExceptionModel exception)
59-
{
60-
var viewModel = new ExceptionViewModel
61-
{
62-
Data = new ObservableCollection<DataViewModel>(exception.Data.Select(d => new DataViewModel
63-
{
64-
Key = d.Key,
65-
Value = d.Value,
66-
})),
67-
Properties = new ObservableCollection<DataViewModel>(exception.Properties.Select(d => new DataViewModel
68-
{
69-
Key = d.Key,
70-
Value = d.Value,
71-
})),
72-
ShowData = exception.Data.Count > 0 ? Visibility.Visible : Visibility.Collapsed,
73-
ShowProperties = exception.Properties.Count > 0 ? Visibility.Visible : Visibility.Collapsed,
74-
HelpLink = exception.HelpLink,
75-
HResult = exception.HResult,
76-
Message = exception.Message,
77-
Source = exception.Source,
78-
StackTrace = exception.StackTrace,
79-
TargetSite = exception.TargetSite,
80-
Demystified = exception.Demystified,
81-
@Type = exception.Type,
82-
};
83-
foreach (var inner in exception.InnerExceptions)
84-
{
85-
viewModel.InnerExceptions.Add(ToViewModel(inner));
86-
}
87-
88-
return viewModel;
89-
}
90-
91-
private void Exception_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
92-
{
93-
var model = sender as ExceptionViewModel;
94-
if (model == null) return;
95-
96-
if (model.IsSelected)
97-
{
98-
ViewModel.SelectedItem = model;
99-
}
100-
}
101-
}
102-
}
1+
using ExceptionVisualizer.Models;
2+
using ExceptionVisualizerSource;
3+
using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers;
4+
using Microsoft.VisualStudio.Extensibility.UI;
5+
using System.Collections.ObjectModel;
6+
using System.Windows;
7+
8+
namespace ExceptionVisualizer
9+
{
10+
internal class ExceptionUserControl(VisualizerTarget visualizerTarget) : RemoteUserControl(new ViewModel())
11+
{
12+
private readonly VisualizerTarget visualizerTarget = visualizerTarget;
13+
14+
private ViewModel ViewModel => (ViewModel)DataContext!;
15+
16+
17+
public override Task ControlLoadedAsync(CancellationToken cancellationToken)
18+
{
19+
_ = Task.Run(async () =>
20+
{
21+
try
22+
{
23+
ExceptionModel? exception = await this.visualizerTarget.ObjectSource.RequestDataAsync<ExceptionModel?>(jsonSerializer: null, CancellationToken.None);
24+
if (exception != null)
25+
{
26+
var viewModel = exception.ToViewModel();
27+
ViewModel.Exceptions.Add(viewModel);
28+
Subscribe(viewModel);
29+
viewModel.IsSelected = true;
30+
}
31+
}
32+
catch (StreamJsonRpc.RemoteInvocationException rie) when (rie.Message.Contains("Could not load file or assembly 'Newtonsoft.Json"))
33+
{
34+
MessageBox.Show("There's currently a bug in Visual Studio causing the Exception Visualizer extension to crash when debugging projects containing a reference to Newtonsoft.Json older than version 13. Either upgrade to version 13 of Newtonsoft.Json or follow this issue on GitHub: https://github.com/microsoft/VSExtensibility/issues/248.");
35+
}
36+
catch (Exception ex)
37+
{
38+
MessageBox.Show($"ExceptionVisualizer failed with exception:\n{ex}");
39+
Telemetry.TrackException(ex);
40+
}
41+
}, cancellationToken);
42+
return Task.CompletedTask;
43+
}
44+
45+
private void Subscribe(ExceptionViewModel model)
46+
{
47+
model.PropertyChanged += Exception_PropertyChanged;
48+
foreach (var inner in model.InnerExceptions)
49+
{
50+
Subscribe(inner);
51+
}
52+
}
53+
54+
private void Exception_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
55+
{
56+
if (sender is not ExceptionViewModel model) return;
57+
58+
if (model.IsSelected)
59+
{
60+
ViewModel.SelectedItem = model;
61+
}
62+
}
63+
}
64+
}

src/ExceptionVisualizer/ExceptionVisualizer.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
</PropertyGroup>
1212

1313
<ItemGroup>
14-
<PackageReference Include="Elmah.Io.Client" Version="5.1.76" />
15-
<PackageReference Include="Elmah.Io.HResults" Version="1.0.23" />
16-
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.11.40261" />
17-
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.11.40261" />
14+
<PackageReference Include="Elmah.Io.Client" Version="5.2.117" />
15+
<PackageReference Include="Elmah.Io.HResults" Version="1.0.29" />
16+
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.12.40390" />
17+
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.12.40390" />
1818
</ItemGroup>
1919

2020
<ItemGroup>
@@ -24,7 +24,7 @@
2424
<Content Include="..\ExceptionVisualizerSource\bin\$(Configuration)\netstandard2.0\ExceptionVisualizerSource.dll" Link="netstandard2.0\ExceptionVisualizerSource.dll">
2525
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2626
</Content>
27-
<Content Include="bin\$(Configuration)\net8.0-windows\Ben.Demystifier.dll" Link="netstandard2.0\Ben.Demystifier.dll">
27+
<Content Include="..\ExceptionVisualizerSource\bin\$(Configuration)\netstandard2.0\Ben.Demystifier.dll" Link="netstandard2.0\Ben.Demystifier.dll">
2828
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2929
</Content>
3030

src/ExceptionVisualizer/Telemetry.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace ExceptionVisualizer
1010
/// </summary>
1111
public static class Telemetry
1212
{
13-
private static IElmahioAPI elmahIoClient;
13+
private static IElmahioAPI? elmahIoClient;
1414

1515
public static bool Enabled { get; set; }
1616

@@ -49,10 +49,10 @@ public static void TrackException(Exception ex)
4949
User = WindowsIdentity.GetCurrent().Name,
5050
Hostname = Hostname(),
5151
Application = "Exception Visualizer",
52-
ServerVariables = new List<Item>
53-
{
52+
ServerVariables =
53+
[
5454
new Item("User-Agent", $"X-ELMAHIO-APPLICATION; OS=Windows; OSVERSION={Environment.OSVersion.Version}; ENGINE=VisualStudio"),
55-
}
55+
]
5656
};
5757

5858
elmahIoClient.Messages.CreateAndNotify(new Guid("ece7db40-a2ea-41f7-838f-9ac9c5514d18"), createMessage);
@@ -75,7 +75,7 @@ private static List<Item> PropertiesToData(Exception exception)
7575
return items;
7676
}
7777

78-
private static string Hostname()
78+
private static string? Hostname()
7979
{
8080
var machineName = Environment.MachineName;
8181
if (!string.IsNullOrWhiteSpace(machineName)) return machineName;

src/ExceptionVisualizerSource/ExceptionModel.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
1+
using System.Collections.Generic;
32
using System.Runtime.Serialization;
43

54
namespace ExceptionVisualizerSource
@@ -20,13 +19,13 @@ public class ExceptionModel
2019
public string Demystified { get; set; }
2120

2221
[DataMember]
23-
public List<KeyValuePair<string, string>> Data { get; set; } = new List<KeyValuePair<string, string>>();
22+
public List<KeyValuePair<string, string>> Data { get; set; } = [];
2423

2524
[DataMember]
26-
public List<KeyValuePair<string, string>> Properties { get; set; } = new List<KeyValuePair<string, string>>();
25+
public List<KeyValuePair<string, string>> Properties { get; set; } = [];
2726

2827
[DataMember]
29-
public List<ExceptionModel> InnerExceptions { get; set; } = new List<ExceptionModel>();
28+
public List<ExceptionModel> InnerExceptions { get; set; } = [];
3029

3130
[DataMember]
3231
public string Source { get; internal set; }

src/ExceptionVisualizerSource/ExceptionModelSource.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,21 @@ private static ExceptionModel Convert(Exception e)
3939
Source = e.Source,
4040
StackTrace = e.StackTrace,
4141
TargetSite = e.TargetSite?.ToString(),
42-
};
43-
model.Data = new List<KeyValuePair<string, string>>(e
42+
Data = new List<KeyValuePair<string, string>>(e
4443
.Data
4544
.Keys
4645
.Cast<object>()
4746
.Where(k => !string.IsNullOrWhiteSpace(k.ToString()))
48-
.Select(i => new KeyValuePair<string, string>(i.ToString(), Value(e.Data, i))));
49-
model.Properties = e
50-
.GetType()
51-
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
52-
.Where(p => p.CanRead)
53-
.Where(p => p.PropertyType.IsSubclassOf(typeof(ValueType)) || p.PropertyType.Equals(typeof(string)))
54-
.Where(p => p.Name != "Message" && p.Name != "Source" && p.Name != "HResult" && p.Name != "HelpLink" && p.Name != "TargetSite" && p.Name != "StackTrace" && p.GetValue(e) != null)
55-
.Select(p => new KeyValuePair<string, string>(p.Name, p.GetValue(e)?.ToString()))
56-
.ToList();
47+
.Select(i => new KeyValuePair<string, string>(i.ToString(), Value(e.Data, i)))),
48+
Properties = e
49+
.GetType()
50+
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
51+
.Where(p => p.CanRead)
52+
.Where(p => p.PropertyType.IsSubclassOf(typeof(ValueType)) || p.PropertyType.Equals(typeof(string)))
53+
.Where(p => p.Name != "Message" && p.Name != "Source" && p.Name != "HResult" && p.Name != "HelpLink" && p.Name != "TargetSite" && p.Name != "StackTrace" && p.GetValue(e) != null)
54+
.Select(p => new KeyValuePair<string, string>(p.Name, p.GetValue(e)?.ToString()))
55+
.ToList()
56+
};
5757
var stackTrace = new EnhancedStackTrace(e);
5858
if (stackTrace.FrameCount > 0)
5959
{

src/ExceptionVisualizerSource/ExceptionVisualizerSource.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<LangVersion>12</LangVersion>
6+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
67
</PropertyGroup>
78

89
<ItemGroup>

0 commit comments

Comments
 (0)