Lets consider that we have an Exception ex thrown in the code. Now in the catch body, I want to have access to six pieces of information:
Solution Name
Project Name
NameSpace Name
File Name
Method Name
Line Number
What I already know is that using
System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(e, true);
I can have access to some of these information(full path of file, line number, etc). But still this information is not all I need. For example, I do not know how to extract solution name or namespace name from trace. Apparently parsing the path for the file is also not an option because different errors can have several layers of file and folders hierarchy and one global rule does not work for all of the errors.
I wonder is there any way to have access programmatically to these info?
Many thanks.
In all likelihood you're not going to get something totally ideal for what you're asking for, but I'll share some tools and thoughts you might not have known about or considered:
There are some attributes (CallerFilePathAttribute, CallerLineNumberAttribute, and CallerMemberNameAttribute which, when added to an optional method parameter, will cause the compiler to automatically insert a default value based on the context of the code being compiled. You could create a helper method with attributes like this to capture the information you want.
There are tools like Fody, known as "IL Weavers", which can run after the main compile process and change the compiled code in a particular way. For example, your code could be written to make a simple call to one method, but when it's compiled the weaver could change the code to create a bunch of contextual information and pass it to a logging method.
If you're organizing your code well, you can often ensure that the namespace, class, and method (which are all captured as part of the stack trace) are enough information that you can guess the solution, project, and File Name.
When you're catching an exception, you typically want to either log what happened and handle the exception in a particular way, or simply wrap the exception in another exception with more contextual information. If you choose the latter, then the namespace, class, and method name will get included in the stack trace of the thrown exception. So when it's logged further up the stack you'll have access to that data.
Related
Referring to What is the correct way to make a custom .NET Exception serializable?
and Are all .NET Exceptions serializable? ...
Why should my exceptions be serializable?
Someone said "it can be considered a bug" if a custom exception defined by a third party library, is not serializable. Why?
Why are exceptions different than other classes in this regard?
Because your exceptions may need to be marshalled between different AppDomains and if they aren't (properly) serializable you will lose precious debugging information. Unlike other classes, you won't have control over whether your exception will be marshalled -- it will.
When I mean "you won't have control" I mean that classes you create generally have a finite space of existence and the existence is well known. If it's a return value and someone tries to call it in a different AppDomain (or on a different machine) they will get a fault and can just say "Don't use it that way." The caller knows they have to convert it into a type that can be serialized (by wrapping the method call). However since exceptions are bubbled up to the very top if not caught they can transcend AppDomain boundaries you didn't even know you had. Your custom application exception 20 levels deep in a different AppDomain might be the exception reported at Main() and nothing along the way is going to convert it into a serializable exception for you.
In addition to Talljoe's answer, your exceptions may be passed across Web Services as well, in this case the exception needs to be serializable/deserializable so it can be turned into XML and transmitted by the Web Service
I think that the default for all classes should be Serializable unless they contain a class that is explicitly not serializable. It's annoying to not be able to transfer a class just because some designer didn't think about it.
The same thing with "Final", all variables should be "Final" by default unless you specifically say that they are "Mutable".
Also, I'm not sure it makes sense to have a variable that is not private.
Oh well, need to design my own language.
But the answer is, you don't know how your exception will be used and they are assumed to be able to be thrown across remote calls.
Another place where objects required to be serializable is Asp.Net Session.
We store last exception in Session and not serializable exceptions needs extra translation to store their details as serializable( specifying original exception as inner doesn't help)
I've noticed that most exception messages don't include instance-specific details like the value that caused the exception. They generally only tell you the "category" of the error.
For example, when attempting to serialize an object with a 3rd. party library, I got a MissingMethodException with message:
"No parameterless constructor defined for this object."
In many cases this is enough, but often (typically during development) a message like
"No parameterless constructor defined for this object of type 'Foo'."
can save a lot of time by directing you straight to the cause of the error.
InvalidArgumentException is another example: it usually tells you the name of the argument but not its value.
This seems to be the case for most framework-raised exceptions, but also for 3rd party libraries.
Is this done on purpose?
Is there a security implication in exposing an internal state like the "faulty" value of a variable?
Two reasons I can think of:
Firstly, maybe the parameter that threw the exception was a value that was a processed form of the one that was passed to the public interface. The value may not make sense without the expense of catching to rethrow a different exception that is going to be the same in most regards anyway.
Secondly, and more importantly, is that there can indeed be a security risk, that can be very hard to second-guess (if I'm writing a general-purpose container, I don't know what contexts it will be used in). We don't want "Credit-Card: 5555444455554444" appearing in an error message if we can help it.
Ultimately, just what debug information is most useful will vary according to the error anyway. If the type, method and (when possible) file and line number isn't enough, it's time to write some debug code that traps just what you do want to know, rather than complaining that it isn't already trapped when next time you might want yet different information (field state of instances can be just as likely to be useful as parameters).
InvalidArgumentException and (per #Ian Nelson) "Key not found in dictionary" both share something in common - there's no guarantee that the framework would be able to find a suitable value to show you - if the key/argument is of any user defined type, and ToString() hasn't been overridden, then you would just get the type name - it's not going to add a lot of value.
Exceptions are mostly meant for a program to consume. Most programs wouldn't know what to do with information about the instance.
The Message property is aimed at human consumption. Other than in a debugging scenario, humans won't know what to make of Foo.
Many exception mechanisms try to serve a hodgepodge of orthogonal purposes by passing a single exception-derived object:
Letting the caller know that various specific things have happened, or that various specific problems exist.
Determining when the exceptional condition is "resolved" so that normal program flow can continue.
Providing an indication of what to tell the user of the program
Providing information which could be logged to allow the owners of a system to identify problems, when a secure log is available
Providing information which could be logged to allow the owners of a system to identify problems, but which would not pose a security risk even if secure logging is not available.
Unfortunately, I'm unaware of any exception mechanism in widespread use which can actually accomplish all five of the above, well.
I'm writing an XML code editor and I want to display syntax errors in the user interface. Because my code editor is strongly constrained to a particular problem domain and audience, I want to rewrite certain XMLException messages to be more meaningful for users. For instance, an exception message like this:
'"' is an unexpected token. The
expected token is '='. Line 30,
position 35
.. is very technical and not very informative to my audience. Instead, I'd like to rewrite it and other messages to something else. For completeness' sake that means I need to build up a dictionary of existing messages mapped to the new message I would like to display instead. To accomplish that I'm going to need a list of all possible messages XMLException can contain.
Is there such a list somewhere? Or can I find out the possible messages through inspection of objects in C#?
Edit: specifically, I am using XmlDocument.LoadXml to parse a string into an XmlDocument, and that method throws an XmlException when there are syntax errors. So specifically, my question is where I can find a list of messages applied to XmlException by XmlDocument.LoadXml. The discussion about there potentially being a limitless variation of actual strings in the Message property of XmlException is moot.
Edit 2: More specifically, I'm not looking for advice as to whether I should be attempting this; I'm just looking for any clues to a way to obtain the various messages. Ben's answer is a step in the right direction. Does anyone know of another way?
Technically there is no such thing, any class that throws an XmlException can set the message to any string. Really it depends on which classes you are using, and how they handle exceptions. It is perfectly possible you may be using a class that includes context specific information in the message, e.g. info about some xml node or attribute that is malformed. In that case the number of unqiue message strings could be infinite depending on the XML that was being processed. It is equally possible that a particular class does not work in this way and has a finite number of messages that occur under specific circumstances. Perhaps a better aproach would be to use try/catch blocks in specific parts of your code, where you understand the processing that is taking place and provide more generic error messages based on what is happening. E.g. in your example you could simply look at the line and character number and produce an error along the lines of "Error processing xml file LineX CharacterY" or even something as general as "error processing file".
Edit:
Further to your edit i think you will have trouble doing what you require. Essentially you are trying to change a text string to another text string based on certain keywords that may be in the string. This is likely to be messy and inconsistent. If you really want to do it i would advise using something like Redgate .net Reflector to reflect out the loadXML method and dig through the code to see how it handles different kinds of syntax errors in the XML and what kind of messages it generates based on what kind of errors it finds. This is likely to be time consuming and dificult. If you want to hide the technical errors but still provide useful info to the user then i would still recomend ignoring the error message and simply pointing the user to the location of the problem in the file.
Just my opinion, but ... spelunking the error messages and altering them before displaying them to the user seems like a really misguided idea.
First, The messages are different for each international language. Even if you could collect them for English, and you're willing to pay the cost, they'll be different for other languages.
Second, even if you are dealing with a single language, there's no way to be sure that an external package hasn't injected a novel XmlException into the scope of LoadXml.
Last, the list of messages is not stable. It may change from release to release.
A better idea is to just emit an appropriate message from your own app, and optionally display -- maybe upon demand -- the original error message contained in the XmlException.
I'm really stumped by this one!
The StackFrame object (MSDN Link) has a GetFileName method that returns the original path of the source file that compiled the executing method (provided symbols were generated and included with the executing assemblies). It looks like this information is used to generate full exception text.
I'm trying to find a way to get at this information if the method isn't currently executing. I've been poking around the reflection API and haven't seen a way to get at this information. I assume it must be in there somewhere.
Does anyone else know of a reflection based method (or indeed any other method) that can get me the code file name?
Any ideas, comments or abuse gratefully accepted.
Many thanks!
Reflection can only provide type information from the assembly metadata. Getting the address requires the .pdb debugging file and the address of the function in memory, as compiled by the JIT compiler. You can't get the address without the StackFrame.GetNativeOffset() method or the debugger interfaces, assuming the method is even compiled. The latter approach can't work in-process, a program cannot debug itself.
The CLR doesn't have any trouble because it can retrieve the method address from the stack frames when it processes the exception. That's still an imperfect art, it cannot see addresses of methods that were inlined. Having those stack frames is the required first step.
You can read the information from the .pdb file and evaluate it yourself. It contains all the data you need. I haven't finished reading the code but my understanding is this:
You get the metadata token from the method in question through reflection
You query the pdb data for that token
The pdb entry contains the source file name and line number
A metadata token is a 32 bit number that consists of a type byte and a serial number. That token describes every single entity in a .NET assembly file: types, type references, methods, fields, and so on. That number is worth more than the full namespace, type, method name and signature of a method, and it's easier to handle. But be aware that it's generated by the compiler and may be different in every build, so you always need the .pdb file from the same build.
The pdb file contains entries about which IL offset in what method comes from which source location. If you don't have a StackFrame but only a method, you'll probably find multiple entries about the method so you can either use the one with the smallest offset, or describe the entire range in the source code that defines the method.
Here are some links for further reading, the search term is "pdb2xml" which is an old code sample by Microsoft:
http://blogs.msdn.com/b/jmstall/archive/2005/08/25/pdb2xml.aspx
http://blogs.msdn.com/b/jmstall/archive/2005/08/25/sample-pdb2xml.aspx
Since the .NET API for reading .pdb files requires to have the assembly files available, this conversion should be done directly after the build to keep the generated XML file really portable.
I'm actually building this method in my .NET logging solution, FieldLog, to allow source location resolution from crash logs from release builds, and to de-obfuscate stack traces from obfuscated assemblies.
Use RedGate Reflector decompiler to inspect the assembly containing the class.
In our solution we have a project that contains all the exceptions.
All of the exceptions inherit our base exception which inherits from ApplicationException.
Our base exception includes a field for exception number.
What I would like to do is to run a script that creates a list with exception name, number and xml documentation.
Any idea how to do this?
If you want to generate a list of the custom exceptions in your application, you can use XML comments for this task. See the accepted answer to this question. As far as I know, the comments will not be able to access the error number property, but you can add an XML comment to that property and state the error number there.
A "script" is not going to be able to do this. You need a static code analyzer that traces all the method calls and detects when an object that derives from Exception is created and thrown. It gets sticky when the code calls methods in the .NET framework, you don't have the source code for it. System.Reflection is no help, it cannot reflect code.
This ultimately goes back to why exception specifications are such a bad idea.
Redgate had a product named "Exception Hunter" to do this. But they gave up on it, couldn't make it reliable enough. The discontinuation announcement is here. Don't buy too much stock on them blaming .NET 4 for this.