I have a web service. Within a method, I have a try-catch block. Then within it, I would like to get the exception code.
I have tried below:
catch (Exception e){
var w32ex = e as Win32Exception;
if(w32ex == null) {
w32ex = e.InnerException as Win32Exception;
}
if(w32ex != null) {
int code = w32ex.ErrorCode;
// do stuff
}
// do other stuff
}
... that is explained here but in my case, it is not working: When casting exception e as Win32Exception I get a null and also once I get a null and I try to cast e.InnerException as Win32Exception I get null as well.
Below a screenshot with my exception:
As you can see there is a HResult code.
According to your screenshot, you're catching an instance of SoapException: https://learn.microsoft.com/en-us/dotnet/api/system.web.services.protocols.soapexception?view=netframework-3.5
This class doesn't inherit from Win32Exception, that's why the type cast operator returns null. You should be able to get HResult field right from the base Exception class (even in .Net 3.5, according to the docs):
catch (Win32Exception w32ex)
{
// Put your current code here...
}
catch (Exception ex)
{
int hResult = ex.HResult;
// Handle HRESULT error code here...
}
Related
Here is a code which I have written
if(Condition)
{
try
{
System.Diagnostics.Process.Start(Path) ;
}
catch ( Win32Exception Error)
{
MessageBox.Show(Error.Message) ;
}
}
Now, when I provided invalid input to
Path
ie a file that does not exist, instead of throwing the Win32 exception, my application is throwing
TargetInvocationError
How can I correct this ? ![enter image description here][1]
Here is the stack trace
I then tried adding the lines
catch(FileNotFoundException Error)
{
MessageBox.Show(Error.Message) ;
}
but still the TargetInvocationException is being thrown.
Either you catch the TargetInvocationException or you catch an exception higher up in the hierarchy, like the base class Exception.
Like this:
try
{
System.Diagnostics.Process.Start(Path) ;
}
catch ( Exception ex)
{
MessageBox.Show(ex.Message) ;
}
The other options is to catch both
try
{
System.Diagnostics.Process.Start(Path) ;
}
catch ( TargetInvocationException ex)
{
MessageBox.Show(ex.Message) ;
}
catch ( Win32Exception ex )
{
MessageBox.Show(ex.Message) ;
}
However, "programming with exceptions" is not recommended (that is, using exceptions as part of your application flow). Instead make sure that Path is valid before you try to use it. Providing an informative message that the path is incorrect instead of giving your users some cryptic message.
try
{
// call to Com Method
}
catch (COMException e)
{
if (e.ErrorCode == 0x80040154) // REGDB_E_CLASSNOTREG.
{
// handle this error.
}
}
I would like to check if com exception is thrown due to REGDB_E_CLASSNOTREG then handle it. I tried with the code above but it gives warning:
Comparison to integral constant is useless; the constant is outside the range of type 'int'
I believe this error is due to 0x80040154 is not in Int32 range.
Can you suggest any possible solution? or Is there any other way to check this?
Use the unchecked keyword:
catch (COMException ex) {
if (ex.ErrorCode == unchecked((int)0x80040514)) {
//...
}
}
Comparing with its integer equivalent works fine:
if (e.ErrorCode == -2147287036) // REGDB_E_CLASSNOTREG.
{
// handle this error.
}
You can also try by using some text that is displayed in Exception message/Error Message like follows
try
{
// call to Com Method
}
catch (COMException e)
{
if (e.ToString().Contains("Your Error Text here")) // REGDB_E_CLASSNOTREG.
{
// handle this error.
}
}
try
{
object result = processClass.InvokeMethod("Create", methodArgs);
}
catch (Exception e)
{
// Here I was hoping to get an error code.
}
When I invoke the above WMI method I am expected to get Access Denied. In my catch block I want to make sure that the exception raised was indeed for Access Denied. Is there a way I can get the error code for it ? Win32 error code for Acceess Denied is 5.
I dont want to search the error message for denied string or anything like that.
Thanks
You can use this to check the exception and the inner exception for a Win32Exception derived exception.
catch (Exception e) {
var w32ex = e as Win32Exception;
if(w32ex == null) {
w32ex = e.InnerException as Win32Exception;
}
if(w32ex != null) {
int code = w32ex.ErrorCode;
// do stuff
}
// do other stuff
}
Starting with C# 6, when can be used in a catch statement to specify a condition that must be true for the handler for a specific exception to execute.
catch (Win32Exception ex) when (ex.InnerException is Win32Exception) {
var w32ex = (Win32Exception)ex.InnerException;
var code = w32ex.ErrorCode;
}
As in the comments, you really need to see what exception is actually being thrown to understand what you can do, and in which case a specific catch is preferred over just catching Exception. Something like:
catch (BlahBlahException ex) {
// do stuff
}
Also System.Exception has a HRESULT
catch (Exception ex) {
var code = ex.HResult;
}
However, it's only available from .NET 4.5 upwards.
Building on Preet Sangha's solution, the following should safely cover the scenario where you're working with a large solution with the potential for several Inner Exceptions.
try
{
object result = processClass.InvokeMethod("Create", methodArgs);
}
catch (Exception e)
{
// Here I was hoping to get an error code.
if (ExceptionContainsErrorCode(e, 10004))
{
// Execute desired actions
}
}
...
private bool ExceptionContainsErrorCode(Exception e, int ErrorCode)
{
Win32Exception winEx = e as Win32Exception;
if (winEx != null && ErrorCode == winEx.ErrorCode)
return true;
if (e.InnerException != null)
return ExceptionContainsErrorCode(e.InnerException, ErrorCode);
return false;
}
This code has been unit tested.
I won't harp too much on the need for coming to appreciate and implement good practice when it comes to Exception Handling by managing each expected Exception Type within their own blocks.
You should look at the members of the thrown exception, particularly .Message and .InnerException.
I would also see whether or not the documentation for InvokeMethod tells you whether it throws some more specialized Exception class than Exception - such as the Win32Exception suggested by #Preet. Catching and just looking at the Exception base class may not be particularly useful.
I suggest you to use Message Properte from The Exception Object Like below code
try
{
object result = processClass.InvokeMethod("Create", methodArgs);
}
catch (Exception e)
{
//use Console.Write(e.Message); from Console Application
//and use MessageBox.Show(e.Message); from WindowsForm and WPF Application
}
catch (Exception e)
{
if (e is MyCustomExeption myEx)
{
var errorCode = myEx.ErrorCode;
}
}
Another method would be to get the error code from the exception class directly. For example:
catch (Exception ex)
{
if (ex.InnerException is ServiceResponseException)
{
ServiceResponseException srex = ex.InnerException as ServiceResponseException;
string ErrorCode = srex.ErrorCode.ToString();
}
}
I have a repository that will throw an EntityNotFoundException when its GetSingle<T>(int id) method cannot find the requested entity in the database. When I use this with AutoMapper and an exception occurs, I get something like this instead:
AutoMapperMappingException: Trying to map CategoryDTO to Category... --->
AutoMapperMappingException: Trying to map System.Int32 to CategoryType... --->
AutoMapper.MappingException: Trying to map System.Int32 to CategoryType... --->
EntityNotFoundException: entity of type CategoryType with ID 5 was not found in the database
My custom exception is 4 levels down. This makes it hard to use try-catch blocks because now I have to do something like this:
try
{
// do the mapping
}
catch (AutoMapperMappingException e)
{
// get the inner-most exception
while (e.InnerException != null)
{
e = e.InnerException;
}
// check to see if it's an EntityNotFoundException
if (e.GetType() == typeof (EntityNotFoundException))
{
var notFound = e as EntityNotFoundException;
// do something specific here, like inform the user
}
else
{
// do something more generic
}
What I'd like to be able to do is just this:
try
{
// do the mapping
}
catch (EntityNotFoundException e)
{
// do something specific here, like inform the user
}
catch (Exception e)
{
// do something more generic
}
Is there any way of disabling AutoMapper's exception wrapping behavior so that I get the straight-up exceptions that are being thrown?
Answer
I ended up creating a thin wrapper around AutoMapper that will catch the AutoMapperMappingException, find the inner-most exception, and throw that:
public class AutoMapperWrapper
{
public TB Map<TA, TB>(TA source, TB destination)
{
// try to do the mapping
try
{
return Mapper.Map(source, destination);
}
// catch AutoMapper's exception
catch (Exception e)
{
// find the first InnerException that's not wrapped
while (e is AutoMapperMappingException)
{
e = e.InnerException;
}
// if the inner exception is null, throw the original exception
if (e == null)
{
throw;
}
// otherwise, throw the inner exception
else
{
throw e;
}
}
}
}
The downside of this method though is that sometimes the entire exception tree is useful to look at to see which property or entity mapping AutoMapper failed on, but this code will only give you the inner-most exception, which is sometimes not very helpful by itself, like InvalidCastException: "could not convert string to int", but won't tell you which property it was.
I thing it would be bad design to conditionally wrap exception so I guess the only thing to do is to drill down into inner exception and find the first none automapperexception.
I've implemented AutoMapperMappingException unwrapping in my NArms.AutoMapper library (see issue). It main purpose is to reduce code amount by providing MapTo<>() extension method which can be used instead of Mapper.Map(). You can get it via NuGet.
Obviously, source code is available at GitHub.
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.