Skip to content

Commit 43810a1

Browse files
committed
Added support for generating and analyzing Silverlight 5 exception stack trace reports
1 parent fe3b25e commit 43810a1

12 files changed

Lines changed: 205 additions & 15 deletions

.nuget/BuildCommon.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<!-- Set compile time constants to detect target framework version during compilation -->
2020
<CustomConstants Condition=" '$(TargetFrameworkVersion)' == 'v2.0' ">TARGET_NET_20</CustomConstants>
2121
<CustomConstants Condition=" '$(TargetFrameworkVersion)' == 'v4.0' ">TARGET_NET_40</CustomConstants>
22+
<CustomConstants Condition=" '$(TargetFrameworkIdentifier)' == 'Silverlight' ">SILVERLIGHT</CustomConstants>
2223
<DefineConstants Condition=" '$(DefineConstants)' != '' And '$(CustomConstants)' != '' ">$(DefineConstants);</DefineConstants>
2324
<DefineConstants>$(DefineConstants)$(CustomConstants)</DefineConstants>
2425
</PropertyGroup>

ProductionStackTrace.Analyze/ExceptionReportInterpreter.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class ExceptionReportInterpreter
3030
// MODULE: AssemblyName => AssemblyFullyQualifiedName; G:27657a27fg376787d6; A:1
3131

3232
private static readonly Regex s_regexAssemblyMapping =
33-
new Regex(@"MODULE: (?<Assembly>[^\s]+(?=\s+\=>))\s+\=>\s+(?<AssemblyFQN>[^;]+)(;\s+(?<KeyValue>[a-z]+\:[^;]+))+", RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
33+
new Regex(@"MODULE: (?<Assembly>[^\s]+(?=\s+\=>))\s+\=>\s+(?<AssemblyFQN>[^;]+)(;(\s+)?(?<KeyValue>[a-z]+\:[^;]+)?)+", RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
3434

3535
private SymbolSearch _symSearch;
3636

@@ -101,6 +101,13 @@ public void Translate(TextReader r, TextWriter w)
101101
info.Attributes[kv[0]] = kv[1];
102102
}
103103

104+
// PDB filename is derived from assembly name + '.pdb' extension
105+
106+
var assemblyFileName = info.FullyQualifiedName;
107+
int idxShortNameEnd = assemblyFileName.IndexOf(',');
108+
if (idxShortNameEnd > 0) assemblyFileName = assemblyFileName.Substring(0, idxShortNameEnd);
109+
var pdbFileName = assemblyFileName + ".pdb";
110+
104111
// If GUID and Age are specified, that means that assembly has debug information
105112
// and the correspodning PDB file would have the matching GUID + Age attributes
106113

@@ -117,21 +124,25 @@ public void Translate(TextReader r, TextWriter w)
117124
info.PdbGuid = pdbGuid;
118125
info.fPdbSpecified = true;
119126

120-
// PDB filename is derived from assembly name + '.pdb' extension
121-
122-
var assemblyFileName = info.FullyQualifiedName;
123-
int idxShortNameEnd = assemblyFileName.IndexOf(',');
124-
if (idxShortNameEnd > 0) assemblyFileName = assemblyFileName.Substring(0, idxShortNameEnd);
125-
126127
// Lookup PDB file using configured Symbol Search Paths. If found, then
127128
// load PDB symbol information - it will be used below to find source line numbers
128129

129-
info.PdbPath = _symSearch.FindPdbFile(assemblyFileName + ".pdb", info.PdbGuid, info.PdbAge);
130-
if (info.PdbPath != null)
131-
info.PdbSymbolLoader = SymbolLoader.Load(info.PdbPath);
130+
info.PdbPath = _symSearch.FindPdbFile(pdbFileName, info.PdbGuid, info.PdbAge);
131+
}
132+
}
133+
else
134+
{
135+
// try to search for it anyway
136+
info.PdbPath = _symSearch.FindPdbFile(pdbFileName);
137+
if (info.PdbPath != null)
138+
{
139+
info.fPdbSpecified = true;
132140
}
133141
}
134142

143+
if (info.PdbPath != null)
144+
info.PdbSymbolLoader = SymbolLoader.Load(info.PdbPath);
145+
135146
mapping[assemblyName] = info;
136147
}
137148
}

ProductionStackTrace.Analyze/ProductionStackTrace.Analyze.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<ItemGroup>
3535
<Reference Include="dia2lib" Condition="'$(TargetFrameworkVersion)' != 'v2.0'">
3636
<HintPath>..\Lib\dia2lib\net40\dia2lib.dll</HintPath>
37-
<EmbedInteropTypes>True</EmbedInteropTypes>
37+
<EmbedInteropTypes>False</EmbedInteropTypes>
3838
</Reference>
3939
<Reference Include="dia2lib" Condition="'$(TargetFrameworkVersion)' == 'v2.0'">
4040
<HintPath>..\Lib\dia2lib\net20\dia2lib.dll</HintPath>

ProductionStackTrace.Analyze/SymbolSearch.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System;
1+
using Dia2Lib;
2+
using System;
23
using System.Collections.Generic;
4+
using System.IO;
35
using System.Runtime.InteropServices;
46
using System.Text;
57

@@ -116,5 +118,32 @@ public string FindPdbFile(string pdbFileName, Guid guid, int age)
116118

117119
return filePath.ToString();
118120
}
121+
122+
/// <summary>
123+
/// Looks through the configured symbol paths to find a PDB symbol
124+
/// file matching specified name.
125+
/// </summary>
126+
/// <param name="pdbFileName">Name of the PDB file.</param>
127+
/// <returns>The pdb file path or null the pdf file wasn't found.</returns>
128+
public string FindPdbFile(string pdbFileName)
129+
{
130+
foreach (string symbolPath in this.SymbolPaths)
131+
{
132+
string filePath = Path.Combine(symbolPath, pdbFileName);
133+
if (File.Exists(filePath))
134+
{
135+
DiaSourceClass dia = new DiaSourceClass();
136+
dia.loadDataFromPdb(filePath);
137+
IDiaSession session;
138+
dia.openSession(out session);
139+
140+
IDiaSymbol symbol = session.globalScope;
141+
142+
return FindPdbFile(pdbFileName, symbol.guid, (int)symbol.age);
143+
}
144+
}
145+
146+
return null;
147+
}
119148
}
120149
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6+
<ProductVersion>8.0.50727</ProductVersion>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{2122731C-6CEA-47E2-A7E1-349523009FAF}</ProjectGuid>
9+
<ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
10+
<OutputType>Library</OutputType>
11+
<AppDesignerFolder>Properties</AppDesignerFolder>
12+
<RootNamespace>ProductionStackTrace</RootNamespace>
13+
<AssemblyName>ProductionStackTrace.Silverlight</AssemblyName>
14+
<TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
15+
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
16+
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
17+
<SilverlightApplication>false</SilverlightApplication>
18+
<ValidateXaml>true</ValidateXaml>
19+
<ThrowErrorsInValidation>true</ThrowErrorsInValidation>
20+
</PropertyGroup>
21+
<!-- This property group is only here to support building this project using the
22+
MSBuild 3.5 toolset. In order to work correctly with this older toolset, it needs
23+
to set the TargetFrameworkVersion to v3.5 -->
24+
<PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
25+
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
26+
</PropertyGroup>
27+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
28+
<DebugSymbols>true</DebugSymbols>
29+
<DebugType>full</DebugType>
30+
<Optimize>false</Optimize>
31+
<OutputPath>Bin\Debug</OutputPath>
32+
<DefineConstants>DEBUG;TRACE;SILVERLIGHT</DefineConstants>
33+
<NoStdLib>true</NoStdLib>
34+
<NoConfig>true</NoConfig>
35+
<ErrorReport>prompt</ErrorReport>
36+
<WarningLevel>4</WarningLevel>
37+
</PropertyGroup>
38+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
39+
<DebugType>pdbonly</DebugType>
40+
<Optimize>true</Optimize>
41+
<OutputPath>Bin\Release</OutputPath>
42+
<DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
43+
<NoStdLib>true</NoStdLib>
44+
<NoConfig>true</NoConfig>
45+
<ErrorReport>prompt</ErrorReport>
46+
<WarningLevel>4</WarningLevel>
47+
</PropertyGroup>
48+
<ItemGroup>
49+
<Reference Include="mscorlib" />
50+
<Reference Include="System.Windows" />
51+
<Reference Include="system" />
52+
<Reference Include="System.Core">
53+
<HintPath>$(TargetFrameworkDirectory)System.Core.dll</HintPath>
54+
</Reference>
55+
<Reference Include="System.Xml" />
56+
<Reference Include="System.Net" />
57+
<Reference Include="System.Windows.Browser" />
58+
</ItemGroup>
59+
<ItemGroup>
60+
<Compile Include="..\ProductionStackTrace\ExceptionEx.cs">
61+
<Link>ExceptionEx.cs</Link>
62+
</Compile>
63+
<Compile Include="..\ProductionStackTrace\ExceptionReporting.cs">
64+
<Link>ExceptionReporting.cs</Link>
65+
</Compile>
66+
<Compile Include="..\ProductionStackTrace\Internals\AssemblyDebugInfo.cs">
67+
<Link>Internals\AssemblyDebugInfo.cs</Link>
68+
</Compile>
69+
<Compile Include="..\ProductionStackTrace\Internals\PeHeaders.cs">
70+
<Link>Internals\PeHeaders.cs</Link>
71+
</Compile>
72+
<Compile Include="Properties\AssemblyInfo.cs" />
73+
</ItemGroup>
74+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
75+
<ProjectExtensions>
76+
<VisualStudio>
77+
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
78+
<SilverlightProjectProperties />
79+
</FlavorProperties>
80+
</VisualStudio>
81+
</ProjectExtensions>
82+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
83+
Other similar extension points exist, see Microsoft.Common.targets.
84+
<Target Name="BeforeBuild">
85+
</Target>
86+
<Target Name="AfterBuild">
87+
</Target>
88+
-->
89+
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("ProductionStackTrace.Silverlight")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCulture("")]
12+
13+
// Setting ComVisible to false makes the types in this assembly not visible
14+
// to COM components. If you need to access a type in this assembly from
15+
// COM, set the ComVisible attribute to true on that type.
16+
[assembly: ComVisible(false)]
17+
18+
// The following GUID is for the ID of the typelib if this project is exposed to COM
19+
[assembly: Guid("2122731c-6cea-47e2-a7e1-349523009faf")]
20+
21+
// Version information for an assembly consists of the following four values:
22+
//
23+
// Major Version
24+
// Minor Version
25+
// Build Number
26+
// Revision
27+
//
28+
// You can specify all the values or you can default the Revision and Build Numbers
29+
// by using the '*' as shown below:
30+
[assembly: AssemblyVersion("1.0.0.0")]
31+
[assembly: AssemblyFileVersion("1.0.0.0")]

ProductionStackTrace.sln

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 2013
4-
VisualStudioVersion = 12.0.21005.1
3+
# Visual Studio 14
4+
VisualStudioVersion = 14.0.25420.1
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductionStackTrace", "ProductionStackTrace\ProductionStackTrace.csproj", "{6F8A759B-6096-468E-A370-09C9785D673C}"
77
EndProject
@@ -27,6 +27,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{03B97452-6
2727
CommonAssemblyInfo.cs = CommonAssemblyInfo.cs
2828
EndProjectSection
2929
EndProject
30+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductionStackTrace.Silverlight", "ProductionStackTrace.Silverlight\ProductionStackTrace.Silverlight.csproj", "{2122731C-6CEA-47E2-A7E1-349523009FAF}"
31+
EndProject
3032
Global
3133
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3234
Debug|Any CPU = Debug|Any CPU
@@ -53,6 +55,10 @@ Global
5355
{AD70438D-18CF-46F5-84DD-4D79B9FB2876}.Debug|Any CPU.Build.0 = Debug|Any CPU
5456
{AD70438D-18CF-46F5-84DD-4D79B9FB2876}.Release|Any CPU.ActiveCfg = Release|Any CPU
5557
{AD70438D-18CF-46F5-84DD-4D79B9FB2876}.Release|Any CPU.Build.0 = Release|Any CPU
58+
{2122731C-6CEA-47E2-A7E1-349523009FAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59+
{2122731C-6CEA-47E2-A7E1-349523009FAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
60+
{2122731C-6CEA-47E2-A7E1-349523009FAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
61+
{2122731C-6CEA-47E2-A7E1-349523009FAF}.Release|Any CPU.Build.0 = Release|Any CPU
5662
EndGlobalSection
5763
GlobalSection(SolutionProperties) = preSolution
5864
HideSolutionNode = FALSE

ProductionStackTrace/ExceptionReporting.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ private static void AppendAssemblyName(StringBuilder builder, Assembly assembly,
228228
if (info == null)
229229
{
230230
ctx.AssemblyInfo.Add(assemblyName, info = new AssemblyReportInfo() { Assembly = assembly, ShortName = originalAssemblyName });
231+
#if !SILVERLIGHT
231232
info.DebugInfo = AssemblyDebugInfo.ReadAssemblyDebugInfo(assembly);
233+
#endif
232234
}
233235
}
234236

ProductionStackTrace/Internals/AssemblyDebugInfo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ private AssemblyDebugInfo()
1818
{
1919
}
2020

21+
#if !SILVERLIGHT
2122
/// <summary>
2223
/// Retrieve PDB information from Assembly, by reading it's PE header.
2324
/// </summary>
@@ -88,6 +89,7 @@ public static AssemblyDebugInfo ReadAssemblyDebugInfo(Assembly assembly)
8889
Path = path
8990
};
9091
}
92+
#endif
9193

9294
#region Struct definitions
9395

ProductionStackTrace/Internals/PeHeaders.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,13 @@ private PeHeaders()
416416
{
417417
}
418418

419+
#if !SILVERLIGHT
419420
public static PeHeaders FromAssembly(Assembly assembly)
420421
{
421422
var modulePtr = Marshal.GetHINSTANCE(assembly.ManifestModule);
422423
return FromUnmanagedPtr(modulePtr);
423424
}
425+
#endif
424426

425427
public static PeHeaders FromUnmanagedPtr(IntPtr memoryPtr)
426428
{
@@ -512,15 +514,25 @@ private static T FromBinaryReader<T>(BinaryReader reader, byte[] lookahead)
512514

513515
// Pin the managed memory while, copy it out the data, then unpin it
514516
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
517+
#if SILVERLIGHT
518+
T theStructure = default(T);
519+
Marshal.PtrToStructure(handle.AddrOfPinnedObject(), theStructure);
520+
#else
515521
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
522+
#endif
516523
handle.Free();
517524

518525
return theStructure;
519526
}
520527

521528
private static T FromMemoryPtr<T>(IntPtr memPtr, ref long index)
522529
{
530+
#if SILVERLIGHT
531+
T obj = default(T);
532+
Marshal.PtrToStructure(new IntPtr(memPtr.ToInt64() + index), obj);
533+
#else
523534
var obj = (T)Marshal.PtrToStructure(new IntPtr(memPtr.ToInt64() + index), typeof(T));
535+
#endif
524536
index += Marshal.SizeOf(typeof(T));
525537
return obj;
526538
}
@@ -594,7 +606,11 @@ public DateTime TimeStamp
594606
// Add in the number of seconds since 1970/1/1
595607
returnValue = returnValue.AddSeconds(fileHeader.TimeDateStamp);
596608
// Adjust to local timezone
609+
#if SILVERLIGHT
610+
returnValue += TimeZoneInfo.Local.GetUtcOffset(returnValue);
611+
#else
597612
returnValue += TimeZone.CurrentTimeZone.GetUtcOffset(returnValue);
613+
#endif
598614

599615
return returnValue;
600616
}

0 commit comments

Comments
 (0)