Debugging exceptions in other applications
I had this recently happen that I referenced a custom library in the configuration of the Semantic Logging Out of Process service only to have an exception get thrown by the service. Unfortunately the ReflectionTypeLoadException output to the console screen lacked critical details not relayed by the ToString method. Rather than trying to debug exactly which of the dozens of libraries being referenced was somehow unloadable, I found a way to get at the exception. If you are lucky, this method may work for you too.
I created a console application that referenced the semantic logging out of process service. I copied all the files the semantic logging out of process service needs to the bin\Debug folder of the project as well. That way when I debug the console application, I'd be able to simulate exactly the kind of behavior it would have had with all the same configuration and libraries present and with only the addition of my console application referencing the executable reporting the error.
I used DotPeek to snoop around the executable to determine a good code entry point. And this is where I got lucky. If every class in the semantic logging out of process service was internal for instance, I would have had no chance of debugging this the way I am currently describing. In the end, I was able to find the class (TraceEventServiceHost) and method (OnStart) that is called when the service is run in console mode and I was able to call them because the class was public and not sealed:
using System;
using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Etw.Service;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
try
{
using (var eventServiceHost = new wrapper())
{
eventServiceHost.Start();
Console.ReadLine();
}
}
catch (ReflectionTypeLoadException ex1)
{
var loaderExceptions = ex1.LoaderExceptions;
foreach (var e in loaderExceptions)
{
Console.WriteLine(e);
}
Console.WriteLine(ex1.ToString());
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
}
private class wrapper : TraceEventServiceHost
{
public void Start()
{
base.OnStart(null);
}
}
}
}
Additionally, I found that the OnStart method was actually protected, so I wrote a class to inherit from
TraceEventServiceHost and call the OnStart method.
I added exception catching for the ReflectionTypeLoadException so that I could finally see the contents of the
LoaderExceptions property. When I debugged this application, I was able to catch the exception in question and
output the additional details. The new details included exceptions saying that the correct versions of
Microsoft.Owin, Microsoft.Owin.Security and Newtonsoft.Json could not be found. This led me to realize that I was
missing binding redirects in the SemanticLogging-svc.exe.config that were now necessary since I added a custom sink.
I was quickly able to add the following to the SemanticLogging-svc.exe.config:
<configuration>
<runtime>
<gcServer enabled="true" />
<gcConcurrent enabled="true" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
After rerunning the service, no exceptions were thrown. Problem solved.
I have since submitted a pull request to the Semantic Logging Application Block project on codeplex to enhance the error output of the Semantic Logging out of process service.
Corrected: pull request is now on github.