Output exception messages including all inners with LINQ - c#

Is it possible to output all error messages of thrown exception including inners via LINQ?
I implemented the functionality without LINQ, but I would like to have more concise code.
(Isn't the purpose of the LINQ?)
My code without LINQ follows:
try {
...
} catch (Exception ex) {
string msg = "Exception thrown with message(s): ";
Exception curEx= ex;
do {
msg += string.Format("\n {0}", curEx.Message);
curEx = curEx.InnerException;
} while (curEx != null);
MessageBox.Show(msg);
}

Linq works on sequences, ie., collections of objects. The exception.InnerException hierarchy is instead nested instances of single objects. What you are doing algorithmically is not inherently a sequence operation, and would not be covered by Linq approaches.
You could define a method that explores the hierarchy and returns (yields) a sequence of objects as they are found, but this ultimately is going to be the same algorithm you're currently using to explore the depths, although you could then choose to apply a sequence operation (Linq) on the results.

To follow up on #Anthony Pegram's answer, you could define an extension method to get a sequence of the inner exceptions:
public static class ExceptionExtensions
{
public static IEnumerable<Exception> GetAllExceptions(this Exception ex)
{
List<Exception> exceptions = new List<Exception>() {ex};
Exception currentEx = ex;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
exceptions.Add(currentEx);
}
return exceptions;
}
}
then you would be able to use LINQ on the sequence. If we have a method that throws nested exceptions like this:
public static class ExceptionThrower {
public static void ThisThrows() {
throw new Exception("ThisThrows");
}
public static void ThisRethrows() {
try {
ExceptionThrower.ThisThrows();
}
catch (Exception ex) {
throw new Exception("ThisRetrows",ex);
}
}
}
here's how you can use LINQ with the little extension method we created:
try {
ExceptionThrower.ThisRethrows();
}
catch(Exception ex) {
// using LINQ to print all the nested Exception Messages
// separated by commas
var s = ex.GetAllExceptions()
.Select(e => e.Message)
.Aggregate((m1, m2) => m1 + ", " + m2);
Console.WriteLine(s);
}

In the current .NET Framework, this is now possible:
string RecursiveStackTrace(Exception ex)
=> $"{ex.Message}<br />{ex.StackTrace}{((ex.InnerException != null) ? $"<br /><br />{RecursiveStackTrace(ex.InnerException)}" : string.Empty)}";

Related

How to catch that there is an error from CommandLineParser so I can return my own error codes?

How to catch that there is an error from CommandLineParser so I can return my own error codes?
I need to return my own codes when my console application is called from say SSIS.
class Program
{
static void Main(string[] args)
{
try
{
var myParserResult = Parser.Default.ParseArguments<UploadFileCommand, DownloadFileCommand, CompressFileCommand>(args)
.WithParsed<ICommand>(t => t.Execute());
var parsed = myParserResult as NotParsed<object>;
if (parsed != null && parsed.Errors.Any())
{
Console.WriteLine("Has Errors");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
The method ParseArguments() will return a ParserResult<T> object to indicate if the parsing was successful or not. In case the parsing was not successful a NotParsed<T> instance is returned. This class has an Errors property to contain all the Error instances why the parsing failed. You can use it in a normal foreach() loop to iterate over the found errors:
ParserResult<Options> result = parser.ParseArguments<Options>(args);
Console.WriteLine(result);
NotParsed<Options> notParsed = result as NotParsed<Options>;
if (notParsed != null)
{
foreach (var error in notParsed.Errors)
{
Console.WriteLine(error);
}
}
This might print the following debug output:
CommandLine.NotParsed`1[Testing.Options]
CommandLine.UnknownOptionError
CommandLine.UnknownOptionError

Exception Handeling For MethodInfo Invoke Method

I have a general retry on exception handler which I would like it to repeat a function for a definite number of time and here's the code for it
public static void Retry(this MethodInfo methodInfo, object[] parametrsList, short after = 0, short? retry = 1)
{
if (retry < 0)
return;
try
{
short waitingPeriodMs = after*1000;
Thread.Sleep(waitingPeriodMs);
Type classObjType = methodInfo.ReflectedType;
object classObj = Activator.CreateInstance(classObjType);
methodInfo.Invoke(classObj, parametrsList);
}
catch (TargetInvocationException ex)
{
Debug.WriteLine("Exception Caught");
methodInfo.Retry(parametrsList, after, --retry);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Caught");
methodInfo.Retry(parametrsList, after, --retry);
}
}
The problem is whenever I an unhandled exception is throw in the method that I'm invoking neither of the two catch statements catches it
I've made sure that the Use Only My Code checkbox is not checked
I've used those two Debug.Writeline statements to make sure that it's not a debugger related issue and checked the Output window and made sure those two statements were not executed
P.S. I'm aware the using a general retry on exception code is risky and could lead to an infinite number of retries the I'm using it because of a project related reason
Update:
A unit test example that reproduces the question
[TestClass]
public class ExceptionTest
{
[TestMethod]
public void TestExceptionRetry()
{
Action act = () => { throw new Exception(); };
act.Method.Retry(new object[0]);
}
}

exception gets handled by the outermost try/catch. windows services

Function that throws the ThirdPartyException (I don't know how does their code work) exception:
private void RequestDocuments(/* arguments... */) {
while(true) {
var revision = lastRevision;
var fetchedDocuments = 0;
try {
foreach(var document in connection.QueryDocuments(revision)) {
if(fetchedDocuments > fetchQuota) return;
container.Add(document);
++fetchedDocuments;
Logger.Log.InfoFormat("added document (revision: {0}) into inner container", document.Revision);
}
Logger.Log.Info("Done importing documents into the inner container");
return;
}
catch(Exception ex) {
if(ex is ThirdPartyException) {
// handle this in a certain way!
continue;
}
}
}
}
this function is called inside a worker thread like this:
private void ImportDocuments() {
while(!this.finishedEvent.WaitOne(0, false)) {
try {
var documents = new List<GohubDocument>();
RequestDocuments(remoteServerConnection, documents, lastRevision, 100);
}
catch(Exception ex) {
// here is where it really gets handled!!!?
}
}
}
the exception is handled only in the outermost (which is inside the ImportDocuments method) try/catch.
Why is that?
If that's a LINQ API which exposes IQueryable you don't get an error due to the deferred execution that LINQ to SQL implementations typically uses.
To prevent it you have to invoke .ToList(), FirstOrDefault() etc within your first method. That makes sure that the query really have been executed against your data source.
Solution:
var documents = connection.QueryDocuments(revision).ToList();
foreach(var document in documents) {
if(fetchedDocuments > fetchQuota) return;
// [...]
}

Find the inner-most exception without using a while loop?

When C# throws an exception, it can have an inner exception. What I want to do is get the inner-most exception, or in other words, the leaf exception that doesn't have an inner exception. I can do this in a while loop:
while (e.InnerException != null)
{
e = e.InnerException;
}
But I was wondering if there was some one-liner I could use to do this instead.
Oneliner :)
while (e.InnerException != null) e = e.InnerException;
Obviously, you can't make it any simpler.
As said in this answer by Glenn McElhoe, it's the only reliable way.
I believe Exception.GetBaseException() does the same thing as these solutions.
Caveat: From various comments we've figured out it doesn't always literally do the same thing, and in some cases the recursive/iterating solution will get you further. It is usually the innermost exception, which is disappointingly inconsistent, thanks to certain types of Exceptions that override the default. However if you catch specific types of exceptions and make reasonably sure they're not oddballs (like AggregateException) then I would expect it gets the legitimate innermost/earliest exception.
Looping through InnerExceptions is the only reliable way.
If the caught exception is an AggregateException, then GetBaseException() returns only the innermost AggregateException.
http://msdn.microsoft.com/en-us/library/system.aggregateexception.getbaseexception.aspx
If you don't know how deep the inner exceptions are nested, there is no way around a loop or recursion.
Of course, you can define an extension method that abstracts this away:
public static class ExceptionExtensions
{
public static Exception GetInnermostException(this Exception e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
while (e.InnerException != null)
{
e = e.InnerException;
}
return e;
}
}
I know this is an old post, but I'm surprised nobody suggested GetBaseException() which is a method on the Exception class:
catch (Exception x)
{
var baseException = x.GetBaseException();
}
This has been around since .NET 1.1. Documentation here:
http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception(v=vs.71).aspx
Sometimes you might have many inner exceptions (many bubbled exceptions).
In which case you might want to do:
List<Exception> es = new List<Exception>();
while(e.InnerException != null)
{
es.add(e.InnerException);
e = e.InnerException
}
You could use recursion to create a method in a utility class somewhere.
public Exception GetFirstException(Exception ex)
{
if(ex.InnerException == null) { return ex; } // end case
else { return GetFirstException(ex.InnerException); } // recurse
}
Use:
try
{
// some code here
}
catch (Exception ex)
{
Exception baseException = GetFirstException(ex);
}
The extension method suggested (good idea #dtb)
public static Exception GetFirstException(this Exception ex)
{
if(ex.InnerException == null) { return ex; } // end case
else { return GetFirstException(ex.InnerException); } // recurse
}
Use:
try
{
// some code here
}
catch (Exception ex)
{
Exception baseException = ex.GetFirstException();
}
Not quite one line but close:
Func<Exception, Exception> last = null;
last = e => e.InnerException == null ? e : last(e.InnerException);
In fact is so simple, you could use Exception.GetBaseException()
Try
//Your code
Catch ex As Exception
MessageBox.Show(ex.GetBaseException().Message, My.Settings.MsgBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
End Try
You have to loop, and having to loop, it's cleaner to move the loop into a separate function.
I created an extension method to deal with this. It returns a list of all of the inner exceptions of the specified type, chasing down Exception.InnerException and AggregateException.InnerExceptions.
In my particular problem, chasing down the inner exceptions was more complicated than usual, because the exceptions were being thrown by the constructors of classes that were being invoked through reflection. The exception we were catching had an InnerException of type TargetInvocationException, and the exceptions we actually needed to look at were buried deep in the tree.
public static class ExceptionExtensions
{
public static IEnumerable<T> innerExceptions<T>(this Exception ex)
where T : Exception
{
var rVal = new List<T>();
Action<Exception> lambda = null;
lambda = (x) =>
{
var xt = x as T;
if (xt != null)
rVal.Add(xt);
if (x.InnerException != null)
lambda(x.InnerException);
var ax = x as AggregateException;
if (ax != null)
{
foreach (var aix in ax.InnerExceptions)
lambda(aix);
}
};
lambda(ex);
return rVal;
}
}
Usage is pretty simple. If, for example, you want to know if we encountered a
catch (Exception ex)
{
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
{
// ...
}
}
I ran into this and wanted to be able to list all of the exception messages from the exception "stack". So, I came up with this.
public static string GetExceptionMessages(Exception ex)
{
if (ex.InnerException is null)
return ex.Message;
else return $"{ex.Message}\n{GetExceptionMessages(ex.InnerException)}";
}
Another way you could do it is by calling GetBaseException() twice:
Exception innermostException = e.GetBaseException().GetBaseException();
This works because if it is an AggregateException, the first call gets you to the innermost non-AggregateException then the second call gets you to the innermost exception of that exception. If the first exception is not an AggregateException, then the second call just returns the same exception.

Catching exception types given as type parameters in C# 2.0

In the following method, the first catch block is never run, even when an exception of type ExceptionType is thrown:
/// <summary>
/// asserts that running the command given throws an exception.
/// </summary>
public static void Throws<ExceptionType>(ICommand cmd)
where ExceptionType : Exception
{
// Strangely, using 2 catch blocks on the code below makes the first catch block do nothing.
try
{
try
{
cmd.Execute();
}
catch (ExceptionType)
{
return;
}
}
catch (Exception f)
{
throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ". Expected type was " + typeof(ExceptionType).Name + ".");
}
throw new AssertionException(cmd.ToString() + " failed to throw a " + typeof(ExceptionType).Name + ".");
}
as indicated by the following test:
[Test]
public void Test_Throws_CatchesSpecifiedException()
{
AssertThat.Throws<AssertionException>(
new FailureCommand()
);
}
using the following class:
class FailureCommand : ICommand
{
public object Execute()
{
Assert.Fail();
return null; // never reached.
}
public override string ToString()
{
return "FailureCommand";
}
}
giving the following output in NUnit:
TestUtil.Tests.AssertThatTests.Test_Throws_CatchesSpecifiedException:
FailureCommand threw an exception of type NUnit.Framework.AssertionException. Expected type was AssertionException.
I also tried using 2 catch blocks for 1 try block (instead of nesting a try/catch within an outer try), but got the same results.
Any ideas as to how to catch the exception specified as a type parameter in one catch block, but catch all other exceptions in the other?
Works fine for me in this test:
using System;
using System.IO;
class Test
{
static void Main()
{
Throws<ArgumentNullException>(() => File.OpenText(null));
}
public static void Throws<ExceptionType>(Action cmd)
where ExceptionType : Exception
{
try
{
try
{
cmd();
}
catch (ExceptionType)
{
Console.WriteLine("Caught!");
return;
}
}
catch (Exception f)
{
Console.WriteLine("Threw an exception of type " + f.GetType()
+ ". Expected type was " + typeof(ExceptionType) + ".");
}
Console.WriteLine("No exception thrown");
}
}
How certain are you that the two AssertionException exceptions are identical? Are they definitely in the same namespace (print typeof(ExceptionType) rather than just the Name property)? Are they from the same assembly? I wouldn't be surprised to find some oddities due to multiple test framework versions coexisting...
Try it with an exception other than AssertionException to make life simpler.
See this thread for more info:
Why can't I catch a generic exception in C#?
Seems to be a bug:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362422&wa=wsignin1.0
I haven't debugged this code or looked at it too long but could it be that you first "return" statement is causing the code to HALT and leave the method. Therefore, the exception is "caught" or "handled" (however you look at it) and the outer try/catch block is never executed.
Are you trying to do this?
try
{
try
{
cmd.Execute();
}
catch (ExceptionType)
{
throw;
}
}
catch (Exception f)
{
throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ". Expected type was " + typeof(ExceptionType).Name + ".");
}

Categories