Better TypeInitializationException (innerException is also null) - c#

Intro
When an user creates a mistake in the configuration of NLog (like invalid XML), We (NLog) throw a NLogConfigurationException. The exception contains the description what is wrong.
But sometimes this NLogConfigurationException is "eaten" by a System.TypeInitializationException if the first call to NLog is from a static field/property.
Example
E.g. if the user has this program:
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
namespace TypeInitializationExceptionTest
{
class Program
{
//this throws a NLogConfigurationException because of bad config. (like invalid XML)
private static Logger logger = LogManager.GetCurrentClassLogger();
static void Main()
{
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
}
and there is a mistake in the config, NLog throws:
throw new NLogConfigurationException("Exception occurred when loading configuration from " + fileName, exception);
But the user will see:
"Copy exception details to the clipboard":
System.TypeInitializationException was unhandled
Message: An unhandled exception of type 'System.TypeInitializationException' occurred in mscorlib.dll
Additional information: The type initializer for 'TypeInitializationExceptionTest.Program' threw an exception.
So the message is gone!
Questions
Why is innerException not visible? (tested in Visual Studio 2013).
Can I send more info to the TypeInitializationException? Like a message? We already sending an innerException.
Can we use another exception or are there properties on Exception so that more info is reported?
Is there another way to give (more) feedback to the user?
Notes
of course we have no influence on the program written by the user.
I'm one of the maintainers of NLog.
Do you like to test it by yourself? Checkout https://github.com/NLog/NLog/tree/TypeInitializationException-tester and start NLog/src/NLog.netfx45.sln
Edit:
please note that I'm the library maintainer, not the user of the library. I cannot change the calling code!

I'll just point out the underlying problem you are dealing with here. You are fighting a bug in the debugger, it has a very simple workaround. Use Tools > Options > Debugging > General > tick the "Use Managed Compatibility Mode" checkbox. Also untick Just My Code for the most informative debugging report:
If Just My Code is ticked then the exception report is less informative but still can be drilled down easily by clicking the "View Detail" link.
The option name is unnecessarily cryptic. What it really does is tell Visual Studio to use an older version of the debugging engine. Anybody that uses VS2013 or VS2015 will have this trouble with the new engine, possibly VS2012. Also the basic reason that this issue did not have be addressed in NLog before.
While this is a very good workaround, it is not exactly easy to discover. Nor would programmers particularly like to use the old engine, shiny new features like return value debugging and E+C for 64-bit code are not supported by the old engine. Whether this is a truly a bug, an oversight or a technical limitation in the new engine is hard to guess. This is excessively ugly so don't hesitate to label it "bug", I strongly recommend you take this to connect.microsoft.com. Everybody will be ahead when it gets fixed, I scratched my head over this at least once that I remember. Drilled it down by using Debug > Windows > Exceptions > ticked CLR Exceptions at the time.
A workaround for this very unfortunate behavior is sure to be ugly. You do have to delay raising the exception until program execution has progressed far enough. I don't know your codebase well enough, but delaying parsing the config until the first logging command ought to take care of it. Or store the exception object and throw it on the first log command, probably easier.

The reason I see is because the Type initialization of Entry point class is failed. Since no type was initialized, so the Type loader has nothing to report about the failed type in TypeInitializationException.
But if you change the Static initializer of logger to other class and then refer that class in Entry method. you'll get the InnerException on TypeInitialization exception.
static class TestClass
{
public static Logger logger = LogManager.GetCurrentClassLogger();
}
class Program
{
static void Main(string[] args)
{
var logger = TestClass.logger;
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
Now you'll get the InnerException because the Entry type was loaded to report the TypeInitializationException.
Hope now you get the idea to keep the Entry point clean and Bootstrap the application from Main() instead of static property of Entry point class.
Update 1
You can also utilize the Lazy<> to avoid the execution of configuration initialization at declaration.
class Program
{
private static Lazy<Logger> logger = new Lazy<Logger>(() => LogManager.GetCurrentClassLogger());
static void Main(string[] args)
{
//this will throw TypeInitialization with InnerException as a NLogConfigurationException because of bad config. (like invalid XML)
logger.Value.Info("Test");
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
Alternatively, try Lazy<> in the LogManager for logger instantiation so that the configuration initialization happens when actually the first log statement occurs.
Update 2
I analyzed the source code of NLog and seems like it's already implemented and It make sense. According to the comments on property "NLog should not throw exception unless specified by property LogManager.ThrowExceptions in LogManager.cs".
Fix - In the LogFactory class the private method GetLogger() has the initialization statement which is causing the exception to happen. If you introduce a try catch with the check of property ThrowExceptions then you can prevent the initialization exception.
if (cacheKey.ConcreteType != null)
{
try
{
newLogger.Initialize(cacheKey.Name, this.GetConfigurationForLogger(cacheKey.Name, this.Configuration), this);
}
catch (Exception ex)
{
if(ThrowExceptions && ex.MustBeRethrown())
throw;
}
}
Also it would be great to have these exceptions/errors stored somewhere so that It can be traced why Logger initialization failed because the they were ignored due to ThrowException.

I said in an earlier comment that I'm unable to reproduce your issue. Then it occurred to me you were only looking for it in the popup exception dialog, which doesn't display a show details link.
So here's how you can get at the InnerException anyway, because it definitely is there, except Visual Studio doesn't report it for some reason (probably because it's in the entry point type as vendettamit figured out).
So, when you run the tester branch, you get the following dialog:
And it doesn't show the View Details link.
The Copy exception detail to the clipboard isn't particularly helpful either:
System.TypeInitializationException was unhandled
Message: An unhandled exception of type 'System.TypeInitializationException' occurred in mscorlib.dll
Additional information: The type initializer for 'TypeInitializationExceptionTest.Program' threw an exception.
Now, dismiss the dialog with the OK button and head towards the Locals debug window. Here's what you'll see:
See? The InnerException definitely is there, and you found a VS quirk :-)

Problem is the static initialization happens when the class is first referenced. In your Program it happens even before the Main() method. So as rule of thumb - avoid any code that can fail in static initialization method. As for your particular problem - use lazy approach instead:
private static Lazy<Logger> logger =
new Lazy<Logger>(() => LogManager.GetCurrentClassLogger());
static void Main() {
logger.Value.Log(...);
}
So the initialization of logger will happen (and possibly fail) when you'll first access the logger - not in some crazy static context.
UPDATE
It is ultimately burden of user of your library to stick to the best practices. So if it were me I'd keep it as it is. There are few options though if you really have to solve it on your end:
1) Don't throw exception - ever - this is valid approach in logging engine, and how log4net works - i.e.
static Logger GetCurrentClassLogger() {
try {
var logger = ...; // current implementation
} catch(Exception e) {
// let the poor guy now something is wrong - provided he is debugging
Debug.WriteLine(e);
// null logger - every single method will do nothing
return new NullLogger();
}
}
2) wrap the lazy approach around the implementation of Logger class (I know your Logger class is much more complex, for sake of this problem let's assume it has just one method Log and it takes string className to construct Logger instance.
class LoggerProxy : Logger {
private Lazy<Logger> m_Logger;
// add all arguments you need to construct the logger instance
public LoggerProxy(string className) {
m_Logger = new Lazy<Logger>(() => return new Logger(className));
}
public void Log(string message) {
m_Logger.Value.Log(message);
}
}
static Logger GetCurrentClassLogger() {
var className = GetClassName();
return new LoggerProxy(className);
}
You'll get rid of this problem (the real initialization will happen while first log method is called and it is backward-compatible approach); only problem is you've added another layer (I don't expect any drastic downgrade of performance, but some logging engines are really into micro-optimization).

The only solution I see now is:
move the static initializes (fields) to a static constructor with a try catch

System.TypeInitializationException is always or almost always occurred from not correct initialisation the static members of a class.
You have to check LogManager.GetCurrentClassLogger() via debugger. I'm sure the error is occurred inside that part of code.
//go into LogManager.GetCurrentClassLogger() method
private static Logger logger = LogManager.GetCurrentClassLogger();
Also i suggest you double check your app.config and make sure you haven't included anything wrong.
System.TypeInitializationException is thrown whenever a static constructor throws an exception, or whenever you attempt to access a class where the static constructor threw an exception.
When .NET loads the type, it must prepare all it's static fields before the first time that you use the type. Sometimes, initialization requires running code. It is when that code fails that you get a System.TypeInitializationException.
According the docs
When a class initializer fails to initialize a type, a TypeInitializationException is created and passed a reference to the exception thrown by the type's class initializer. The InnerException property of TypeInitializationException holds the underlying exception.
TypeInitializationException uses the HRESULT COR_E_TYPEINITIALIZATION, that has the value 0x80131534.
For a list of initial property values for an instance of TypeInitializationException, see the TypeInitializationException constructors.
1) The InnerException is not visible it is very typical for this type of Exception. The version of Visual Studio doesn't matter (ensure that the "Enable the exception assistant" option is checked - Tools> Options>Debugging>General)
2) Usually the TypeInitializationException hides the real exception which can be viewed via InnerException. But the test example below shows how you can populate inner exception info:
public class Test {
static Test() {
throw new Exception("InnerExc of TypeInitializationExc");
}
static void Main(string[] args) {
}
}
But sometimes this NLogConfigurationException is "eaten" by an
System.TypeInitializationException if the first call to NLog is from a
static field/property.
Nothing strange. Someone missed the try catch block somewhere.

Related

How does the console obtain the stack trace of an exception?

In C# I'm trying to modify the StackTrace property of a custom exception I created. For this, I just override the StackTrace getter and it seems to be working (Exception has it as a virtual method, so it should work). This is my custom exception:
class CustomTimeoutException : Exception
{
private string oldStack;
public CustomTimeoutException(string message, String stack)
: base(message)
{
oldStack = stack;
}
public override string StackTrace
{
get
{
return oldStack;
}
}
public override string Message
{
get
{
return "lalalala2";
}
}
public override System.Collections.IDictionary Data
{
get
{
return null;
}
}
}
I'm using this class the following way:
class Program
{
static void Main(string[] args)
{
try
{
Program p = new Program();
p.throwTimeout2();
}
catch(TimeoutException e)
{
CustomTimeoutException tor = new CustomTimeoutException(e.Message + "with more", e.StackTrace);
Console.WriteLine(tor);
Console.WriteLine(tor.StackTrace);
throw tor;
}
}
public void throwTimeout2()
{
throwTimeout();
}
public void throwTimeout()
{
throw new TimeoutException("this is a message ");
}
}
When I write the property StackTrace to the console, it prints the StackTrace of the TimeoutException, which means it's in fact overriding it. But, when the console shows the error, the StackTrace is not the one it gets from my property, yet the Message is the one it gets from the Message property I'm also overriding.
So, where does the console get the StackTrace of the exception from? I'm using Visual Studio for running.
(Note: one thing I still really don't understand about your question is that, while you seem to be asking for a way to affect how an exception is reported to the console, you also say that you have some "tool" that apparently has access to the Exception object itself and is reporting on the inner-most exception, i.e. following the InnerException property chain until it reaches the last one. These two statements seem to be in contradiction with each other, so I'm not really sure I completely understand the question. Still, I spent some time looking into it, and will share what I have regardless. :) .)
IMHO, there is not a good way to do what you want. There is an ugly way (see below), but I don't recommend it. Especially since your main limitation is the "tool that uses the message"; it is IMHO a very bad idea to go changing production code just to suit some tool. That path leads to big maintenance headaches, if not outright buggy code.
If you really must change the exception message, you should just bite the bullet and toss the entire stack trace text you want to preserve into the message as well. Trying to mess around with the stack trace of the eventually-thrown exception itself is bad news.
That said…
If you were to add diagnostic calls to Console.WriteLine() to your method overrides, you would confirm (as you've probably already guessed) that the StackTrace property is not called when the exception is re-thrown and reported by the CLR to the console. Overriding the property is not going to help.
There are at least two problems with trying that strategy:
The StackTrace property is just a string containing formatted information about the stack trace. The Exception object does actually contain a private field _stackTrace. When you execute the throw statement with an Exception object, the CLR stores the current stack trace information into this field. You would have to find some way to overwrite this field after the fact, to fake a throw site different from the actual one.
The CLR exception handling leverages existing Windows exception handling infrastructure. One of the first things that happens when an exception is thrown is the exception handling code attempts to find a handler up the stack. If it fails to find one, then you get the "Unhandled Exception:" message. But note that in the process, the stack has not been unwound. Thus, the exception handling code does not even need to inspect the Exception object at all to determine the throw site; the stack is still there, and its state can be reported directly. There is literally nothing you can do with the Exception object that would affect reporting, if indeed the exception handling code is looking directly at the stack state.
Now, as it happens, for the version of .NET I'm running on my Windows 8.1 machine, it appears that the CLR is reporting the stack trace as stored in the Exception object and not directly inspecting the stack, per option #2 above. So something like this actually works:
ExceptionWrapper class
class ExceptionWrapper : Exception
{
private readonly string _trace;
private readonly string _message;
private readonly string _toString;
private readonly object _stackTrace;
public ExceptionWrapper(Exception e)
{
_trace = e.StackTrace;
_message = e.Message + ", wrapped";
_toString = e.ToString();
_stackTrace = typeof(Exception).GetField("_stackTrace",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e);
}
public override string StackTrace { get { return _trace; } }
public override string Message
{
get
{
typeof(Exception)
.GetField("_stackTrace", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, _stackTrace);
return _message;
}
}
public override string ToString() { return _toString; }
}
Test program
class Program
{
static void Main(string[] args)
{
try
{
M1();
}
catch (Exception e)
{
throw;
}
}
private static void M1()
{
try
{
M();
}
catch (Exception e)
{
throw new ExceptionWrapper(e);
}
}
static void M()
{
throw new Exception("test exception");
}
}
There is a very significant caveat though. This works only because of two specific facts:
The CLR is not taking advantage of the current stack state, but instead is trusting the Exception object to contain correct stack information in the _stackTrace field.
The CLR calls the Message getter of the Exception object before retrieving the stack trace. This gives the object an opportunity to overwrite the _stackTrace field before the CLR accesses it for the purpose of reporting the stack trace.
Both of these are, as near as I can tell, completely undocumented implementation details. The second one in particular is very fragile; while I can see why the CLR might always have to stick with the first detail, I see no reason at all that Microsoft (never mind other implementors of the CLS) should feel compelled to preserve the behavior in the second point.
Writing code that relies on these implementation details is just asking for trouble. Whatever the broader goal here is, I simply cannot imagine it would be worthwhile to suffer the risk of breaking your project for this need. IMHO, it would be much more reasonable to simply rewrite this "tool" you are trying to accommodate.
Tools are (or at least should be) inherently simple in nature, and not only would rewriting it allow you to produce the results you want without mucking around with private implementation details in third-party code, it would also give you the chance to a) add new features, such as providing options for controlling how to process exception data (e.g. looking at something other than the inner-most exception), and b) have a tool for which you do have the source code, with which you can make further improvements in the future.
I strongly advise that you not paint yourself into this particular corner. :)

Why are exceptions in a static constructor wrapped in TypeInitializationException

The exception from a static constructor is wrapped in a TypeInitializationException. Consider the example below
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
try
{
new MyClass();
}
catch (Exception e)
{
Console.WriteLine(e.GetType().ToString());
}
}
public class MyClass
{
static MyClass()
{
throw new Exception();
}
}
}
}
The output of the program is
System.TypeInitializationException
What are the reasons for wrapping the exception in a TypeInitializationException ?
Why is the original exception not returned ?
What are the reasons for wrapping the exception in a TypeInitializationException ?
Exceptions in static constructors are difficult. Basic issue is that the execution context of the exception is very vague. The CLI does not give any specific promise exactly when the constructor runs. Only guarantee is that it will run soon enough, how soon is unspecified.
So a dooms-day scenario without the exception being wrapped is that you get a vague bug report from a user like "I get a NullReferenceException when I click the Save button". You'll study your SaveButton_Click() event handler but no matter how hard you look, you'll never find a good reason for that exception. It occurred in code that's far removed from the event handler method, code that ran at an unpredictable time.
By wrapping it in TypeInitializationException, you'll know where to look.
Why is the original exception not returned ?
It is returned, it will be the InnerException of the TIE. Forgetting to look at it is a standard oversight. If you ever write try/catch code then never make the mistake of only displaying Message property of the exception you caught. The InnerException is important too. Strongly favor displaying the string generated by the exception object's ToString() method. It is gobbledegooky to the user but essential to you. Avoid the gobble with logging or hiding details that can be revealed with "Details" button in the error dialog.
Static constructors are called on initialization, so although it's your static constructor that's failing, it's the type initalizer that's calling that, so that's the exception you get: https://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx

What's a good global exception handling strategy for Unity3D?

I'm looking into doing some Unity3D scripting stuff, and I'd like to set up global exception handling system. This is not for running in the release version of the game, the intention is to catch exceptions in user scripts and also in editor scripts and make sure they are forwarded to a database for analysis (and also to send email to relevant devs so they can fix their shizzle).
In a vanilla C# app I'd have a try-catch around the Main method. In WPF I'd hook one or more of the unhandled exception events. In Unity...?
So far the best I've been able to come up with is something like this:
using UnityEngine;
using System.Collections;
public abstract class BehaviourBase : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
try
{
performUpdate();
print("hello");
}
catch (System.Exception e)
{
print(e.ToString());
}
}
public abstract void performUpdate();
}
In other scripts, I derive BehaviourBase instead of MonoBehavior and implement performUpdate() instead of Update(). I haven't implemented a parallel version for Editor clases but I assume I'd have to do the same thing there.
I don't like this strategy, however, because I'll have to backport it to any scripts we grab from the community (and I'll have to enforce it on the team). The Editor scripts don't have a single point of entry comparable to MonoBehavior either, so I assume I'd have to implement exception safe versions of wizards, editors and so on.
I've seen suggestions about catching log messages (as opposed to exceptions) using Application.RegisterLogCallback, but this makes me uncomfortable because I'd need to parse the debug log string rather than having access to the actual exceptions and stacktraces.
So... what's the right thing to do?
Create an empty GameObject in your scene and attach this script to it:
using UnityEngine;
public class ExceptionManager : MonoBehaviour
{
void Awake()
{
Application.logMessageReceived += HandleException;
DontDestroyOnLoad(gameObject);
}
void HandleException(string logString, string stackTrace, LogType type)
{
if (type == LogType.Exception)
{
//handle here
}
}
}
make sure there is one instance.
The rest is up to you. You can also store the logs in file system, web server or cloud storage.
Note that DontDestroyOnLoad(gameObject) makes this GameObject persistent, by preventing it from being destroyed in case of scene change.
There is a working implementation of RegisterLogCallback that I found here: http://answers.unity3d.com/questions/47659/callback-for-unhandled-exceptions.html
In my own implementation I use it to call my own MessageBox.Show instead of writing to a log file. I just call SetupExceptionHandling from each of my scenes.
static bool isExceptionHandlingSetup;
public static void SetupExceptionHandling()
{
if (!isExceptionHandlingSetup)
{
isExceptionHandlingSetup = true;
Application.RegisterLogCallback(HandleException);
}
}
static void HandleException(string condition, string stackTrace, LogType type)
{
if (type == LogType.Exception)
{
MessageBox.Show(condition + "\n" + stackTrace);
}
}
I also now have the error handler email me via this routine, so I always know when my app crashes and get as much detail as possible.
internal static void ReportCrash(string message, string stack)
{
//Debug.Log("Report Crash");
var errorMessage = new StringBuilder();
errorMessage.AppendLine("FreeCell Quest " + Application.platform);
errorMessage.AppendLine();
errorMessage.AppendLine(message);
errorMessage.AppendLine(stack);
//if (exception.InnerException != null) {
// errorMessage.Append("\n\n ***INNER EXCEPTION*** \n");
// errorMessage.Append(exception.InnerException.ToString());
//}
errorMessage.AppendFormat
(
"{0} {1} {2} {3}\n{4}, {5}, {6}, {7}x {8}\n{9}x{10} {11}dpi FullScreen {12}, {13}, {14} vmem: {15} Fill: {16} Max Texture: {17}\n\nScene {18}, Unity Version {19}, Ads Disabled {18}",
SystemInfo.deviceModel,
SystemInfo.deviceName,
SystemInfo.deviceType,
SystemInfo.deviceUniqueIdentifier,
SystemInfo.operatingSystem,
Localization.language,
SystemInfo.systemMemorySize,
SystemInfo.processorCount,
SystemInfo.processorType,
Screen.currentResolution.width,
Screen.currentResolution.height,
Screen.dpi,
Screen.fullScreen,
SystemInfo.graphicsDeviceName,
SystemInfo.graphicsDeviceVendor,
SystemInfo.graphicsMemorySize,
SystemInfo.graphicsPixelFillrate,
SystemInfo.maxTextureSize,
Application.loadedLevelName,
Application.unityVersion,
GameSettings.AdsDisabled
);
//if (Main.Player != null) {
// errorMessage.Append("\n\n ***PLAYER*** \n");
// errorMessage.Append(XamlServices.Save(Main.Player));
//}
try {
using (var client = new WebClient()) {
var arguments = new NameValueCollection();
//if (loginResult != null)
// arguments.Add("SessionId", loginResult.SessionId.ToString());
arguments.Add("report", errorMessage.ToString());
var result = Encoding.ASCII.GetString(client.UploadValues(serviceAddress + "/ReportCrash", arguments));
//Debug.Log(result);
}
} catch (WebException e) {
Debug.Log("Report Crash: " + e.ToString());
}
}
Unity devs just do not provide us with tools like that. They catch exceptions internally in framework here and there and log them as strings, giving us Application.logMessageReceived[Threaded]. So, if you need exceptions to happen or be logged with your own processing (not unity's) I can think of:
do not use framework mechanics, but use your own so exception is not caught by framework
make your own class implementing UnityEngine.ILogHandler:
public interface ILogHandler
{
void LogFormat(LogType logType, Object context, string format, params object[] args);
void LogException(Exception exception, Object context);
}
And use it as said in official docs to log your exceptions. But that way you do not receive unhandled exceptions and exceptions logged from plugins (yes, someone do log exceptions in frameworks instead of throwing them)
Or you can make a suggestion/request to unity to make Debug.unityLogger (Debug.logger is deprecated in Unity 2017) have setter or other mechanism so we can pass our own.
Just set it with reflection. But it's temporary hack and will not work when unity change code.
var field = typeof(UnityEngine.Debug)
.GetField("s_Logger", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, your_debug_logger);
Note: To get correct stacktraces you need to set StackTraceLogType in editor settings/code to ScriptOnly (most times it's what you need, I wrote an article on how it work) And, when building for iOS, it is said that Script call optimization must be set to slow and safe
If interested, you can read how popular crash analytics tool works. If you look into crashlytics (crash report tool for android/ios), than you'll find out that it internally uses Application.logMessageReceived and AppDomain.CurrentDomain.UnhandledException events to log managed C# exceptions.
If interested in examples on unity framework catching exceptions, you may look at ExecuteEvents.Update And another article from me with testing it catching exception in button click listener can be found here.
Some summary on official ways to log unhandled exception:
I. Application.logMessageReceived is fired when exception happens on main thread. There are ways for it to happen:
exception caught in c# code and logged through Debug.LogException
exception caught in native code (probably c++ code when using il2cpp). In that case native code calls Application.CallLogCallback which results in firing Application.logMessageReceived
Note: StackTrace string will contain "rethrow" when original exception have inner exceptions
II. Application.logMessageReceivedThreaded is fired when exception happens on any thread, including main (it's said in docs) Note: it must be thread-safe
III. AppDomain.CurrentDomain.UnhandledException for example is fired when:
You call the following code in editor:
new Thread(() =>
{
Thread.Sleep(10000);
object o = null;
o.ToString();
}).Start();
But it causes crash on android 4.4.2 release build when using Unity 5.5.1f1
Note: I reproduced some bugs with unity missing stackframes when logging exceptions and assertions. I submited one of them.
You mentioned Application.RegisterLogCallback, have you tried implementing it? Because the logging callback passes back a stack trace, an error, and an error type (warning, error, etc).
The strategy you outline above would be tough to implement because MonoBehaviours don't just have a single entry point. You'd have to handle OnTriggerEvent, OnCollisionEvent, OnGUI, and so on. Each one wrapping its logic in an exception handler.
IMHO, exception handling is a bad idea here. If you don't immediately re-throw the exception, you'll end up propagating those errors in weird ways. Maybe Foo relies on Bar, and Bar on Baz. Say Baz throws an exception that is caught and logged. Then Bar throws an exception because the value it needs from Baz is incorrect. Finally Foo throws an exception because the value it was getting from Bar is invalid.
You can use a plugin called Reporter to receive an email of Debug Logs, Stack trace and screen capture on the moment of unhandled Error. Screen capture and stack trace are usually enough to figure out the reason of the Error. For stubborn sneaky Errors you should log more of suspicious data, build and wait again for the error.I Hope this helps.

Unhandled Exception in C# Console Application causing AppCrash

I have a Windows Console application built in Visual Studio 2010 and it keeps crashing but the error is not caught by the visual studio debugging tool nor by try/catch statements in my code.
I have managed to locate the WER file on my system and would like to be able to understand the contents of the file so I can pinpoint exactally what is causing the unhandled exception.
I would be greatful if anyone can offer some idea on how I can use the following information to locate the process causing me this problem and also what the exception may be...
The information from the WER file is:
Version=1
EventType=APPCRASH
EventTime=129973086237604286
ReportType=2
Consent=1
ReportIdentifier=91331e8b-2dc8-11e2-977b-080027f7e5bb
IntegratorReportIdentifier=91331e8a-2dc8-11e2-977b-080027f7e5bb
WOW64=1
Response.type=4
Sig[0].Name=Application Name
Sig[0].Value=SAGE_TESTING.vshost.exe
Sig[1].Name=Application Version
Sig[1].Value=10.0.30319.1
Sig[2].Name=Application Timestamp
Sig[2].Value=4ba2084b
Sig[3].Name=Fault Module Name
Sig[3].Value=ntdll.dll
Sig[4].Name=Fault Module Version
Sig[4].Value=6.1.7600.16385
Sig[5].Name=Fault Module Timestamp
Sig[5].Value=4a5bdb3b
Sig[6].Name=Exception Code
Sig[6].Value=c015000f
Sig[7].Name=Exception Offset
Sig[7].Value=000845bb
DynamicSig[1].Name=OS Version
DynamicSig[1].Value=6.1.7600.2.0.0.272.7
DynamicSig[2].Name=Locale ID
DynamicSig[2].Value=2057
DynamicSig[22].Name=Additional Information 1
DynamicSig[22].Value=0a9e
DynamicSig[23].Name=Additional Information 2
DynamicSig[23].Value=0a9e372d3b4ad19135b953a78882e789
DynamicSig[24].Name=Additional Information 3
DynamicSig[24].Value=0a9e
DynamicSig[25].Name=Additional Information 4
DynamicSig[25].Value=0a9e372d3b4ad19135b953a78882e789
Here is the section of code I believe to be causing the exception to be thrown:
//Data from the project linked to the split data
if (oSplitData.Project != null)
{
oProject = oSplitData.Project as SageDataObject190.Project;
oBasicDetail.ProjectID = oProject.ProjectID;
oBasicDetail.ProjectReference = oProject.Reference.ToString();
}
else
{
oBasicDetail.ProjectID = -1;
oBasicDetail.ProjectReference = "NO_PROJECT";
}
To add to all the above I seem to have found that there is a general exception that is being thrown but it doesn't help me out much - if anyone can put some light on this it would be great:
Unhandled exception at 0x78bc7361 in SAGE_TESTING.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
If your program is multi-threaded and the exception is thrown in one of the spawned threads, the Exception may not be caught depending on how you do exception handling in your program.
You can add a catch-all exception handler like this:
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
// Your code here
}
static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine(e.ExceptionObject.ToString());
Environment.Exit(1);
}
}
UPDATE
Based on the code you posted, here are some things to look at
Put a try/catch block around the code you posted.
Are you sure that oSplitData is not null?
In the following line, oProject will be null if oSplitData.Project is not of type SageDataObject190.Project. Test for null.
oProject = oSplitData.Project as SageDataObject190.Project;
You are probably dealing with so-called corrupted state exceptions. These exceptions corrupt the process in a way so it is usually more safe to kill the process since it is very difficult to impossible to recover from such an error, even if it would be only for running a short catch-clause. Examples are StackOverflowExceptions, OutOfMemoryExceptions or AccessViolationExceptions.
There is an extensive and generally interesting explanation on corrupted state exceptions in this article.
What is helpful on getting a hand on such exceptions is to use DebugDiag. With this tool from Microsoft (download on this page) you can define a crash rule which generates a crashdump for your failed process. You can easily open these dump files in Visual Studio, where you may find the source of the exception that lead to the failure. This is not guaranteed but it often helped me in the past to nail down some nasty errors.
Are you invoking non-managed C++ or other code?
I'd try something like
static void Main()
{
try
{
DoSomethingUseful() ;
}
catch ( Exception e )
{
// managed exceptions caught here
}
catch
{
// non-managed C++ or other code can throw non-exception objects
// they are caught here.
}
return ;
}
See Will CLR handle both CLS-Complaint and non-CLS complaint exceptions?
Also C++ try, catch and throw statements at msdn: http://msdn.microsoft.com/en-us/library/6dekhbbc(v=vs.100).aspx
And MSIL opcode throw (0x7A) allows the throwing any object reference. C#, however, does not allow it.
But it looks like they improved things with .Net 2.0 and started wrapping oddball stuff in an RuntimeWrappedException.

VS2010 did not break debug on static constructor exception

I have a Windows Forms application with a single Editor class (that inherits from Form).
public partial class Editor : Form
{
public Editor()
{
InitializeComponent();
Load += Editor_Load;
}
private void Editor_Load(object sender, EventArgs e)
{
cmbConnections.DataSource = ConnectionManager.Connections;
cmbConnections.Visible = false;
}
}
Other than designer-generated code, this is the only code for the form (that contains only a single Combo Box (cmbConnections).
The ConnectionManager class is a static class with a static constructor. It's constructor does some initialization and then tests for some critical condition. If the condition is met, the constructor throws an exception. However, this exception does not break in the debugging mode in Visual Studio 2010. To test this, I've put only throw new Exception() in the ConnectionManager's static constructor. The ConnectionManager is used and therefor initialized (for the first time) in the Editor_Load event handler. Static constructor is called and exception thrown (visible only in output window). The rest of the Editor_Load event handler (cmbConnections.Visible = false;) is not executed, just as expected.
But what I don't understand is why did my VS2010 swallow the exception? It did not break the debug. It is not enclosed in any try/catch block. It continued with program execution with the main window. It almost seems as if the Editor_Load was executed on another thread.
I can see the messages in output window:
A first chance exception of type 'System.InvalidOperationException' occurred in Editor.exe
A first chance exception of type 'System.TypeInitializationException' occurred in Editor.exe
but the execution simply did not break in debug mode.
Here are some of my options that I believe may influence this behavior:
Project Properties->Build->General-> Optimize code is UNCHECKED.
Tools->Options->Debugging->General-> Enable Just My Code is CHECKED.
In exception settings, the checkbox for the "user-unhandled" is CHECKED.
Am I missing something? Is this behavior normal? I thought that VS2010 will throw on ANY unhandled exception. And here this one is unhandled and still does not break.
I think it is by design that you need to enable Managed (.NET) Exceptions 'Thrown' in the Exceptions Dialog (Ctrl-Alt-E).1
To avoid many spurious (handled) exceptions, I usually try to get close to the point where the initializer will be run and then check that checkbox just before continueing.
Also, if there are loader exceptions, be sure to check the nested inner exceptions or loader information in the exception: the exception itself is usually not that informative. I have frequently had to dig through 2 or more layers of wrapping exceptions in order to get at the actual error.
1 I can only guess as to why that is; My feeling is that the static type initializers are not considered to be run deterministically (many things could trigger it and the order is often undefined; it is just guaranteed that a type's static constructor will have been run before it is used, but it can be used at almost any point in the code, without you knowing or explicitely triggering that).
Therefore, it would be hard for the runtime to establish whether it was 'handled by user code' (no user should expect to handle it, because it doesn't know - deterministically - when the initializer will run).
However, this is conjecture on my part.

Categories

Resources