Other than reading the GetFileName() file and reading to line GetFileLineNumber() of a stackframe from
new StackTrace(exception).GetFrame(x)
is there a way to get the actual line of code (as a string) which caused an exception?
Thanks
I don't think so. The code is compiled, therefore it is no longer available.
However, if you also have the source code available, there may be a few workarounds.
No, that's your only option as far as I know. In order to get the original line of code that caused the exception, then it's necessary to have the source available. That the StackFrame already enables you to get the line number (via the debug symbols - the PDB file in most cases), makes it straightforward enough, I'd say.
Is there any particular problem with the method you suggested?
There is no reliable way to do this because line information is not stored in DLL files. The information which maps blocks of IL into source code lines is stored within the PDB file. You'd need to access the PDB in order to get the line information for an exception.
There is sufficient information on the StackFrame class to get the appropriate ISymUnmanagedMethod class if the PDB is available. Mainly you just need the method token and the current offset into the method. This does require you to understand the internal structure of the PDB and I'm not sure if it's documented anywhere.
PDB API: http://msdn.microsoft.com/en-us/library/ms233503.aspx
It would be compiled, so at run time you would only have the IL. At best, you could get the IL and decompile it back to C#, much like reflector does.
Post moretem debugging is difficult, but not impossible. There are tools you can use (here and here for example) as well as techniques.
You can get line using a try catch block:
catch(Exception exception) {
//exception.StackTrace at the first line has the line you are looking for
}
Related
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.
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.
I am using Windbg to load a crash dump from managed code (C#, a console application built for Any CPU), and crash dump is created on x64 platform. I am debugging on x64 platform.
I have using the following command to load private symbol of my application. Here are what the commands I am using in Windbg.
(set symbol path and copy FooService.pdb pdb file to local symbol path D:\Debug)
0:016> .reload /f
.*** WARNING: Unable to verify checksum for FooService.exe
DBGHELP: FooService.pdb- private symbols & lines
D:\Debug\FooService.pdb
0:016> lm
start end module name
00000000`00400000 00000000`0041c000 FooService C (private pdb symbols) D:\Debug\FooService.pdb
My confusion is, when using the following command, no line number information is showed in stack trace. Any ideas what is wrong? Do I need to set source path?
0:016> ~6 e!clrstack
EDIT 1: I met with some issues with using !pe and !U to find stack trace where the exception is thrown.
Here is my debug process. At first I use !pe to print stack trace for the exception object, when I use !U to diassemble the code. The issue I find is !U will diassemble all function code of FooService.ProcessOrders(), and I want to find the exact place where in function FooService.ProcessOrders the crash happens. I also find the diassembled annotated IL code only contains function calls I made (for non-function call C# code, for example a=a*2, only assembly language is shown), not exactly IL mapped to each line of C# code, (1) is that the correct expected behavior? (2) what is the solution or further suggestion to find the exact failed C# code from my analysis posted here?
!pe 0000064280155325
StackTrace (generated):
SP IP Function
000000001A56DA70 00000642B74E3B7A System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(System.Data.Common.DbAsyncResult, System.String, Boolean)
000000001A56DB10 00000642B74E3FCC System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
000000001A56DB90 0000064280155325 FooService.ProcessOrders()
000000001A56F3E0 0000064280153A21 FooService.RountineJob()
!U 0000064280155325
thank in advance,
George
WinDbg/SOS doesn't map line numbers to the output of !clrstack. So as long as lm tells you that you have private pdb symbols for your own assemblies you setup is correct. Unfortuntately the current versions of WinDbg/SOS doesn't support source level debugging to the same extend as for native code.
EDIT: Regarding exceptions. When you do a !pe, it will tell you the call stack as well as offsets into the relevant methods. If you take the address from the IP column of the !pe output and do a !U on that, you will see the JITTED code for the relevant method. The IP column will be the last address of the code that generated the exception (so you have to do a little counting to find the correct instruction).
The disassembled output is annotated with .NET calls so it is no hard to map this against the IL or source code. That should help you identify exactly which throw statement you're looking for.
That being said, you will make debugging a lot easier if you split methods into a number of smaller methods. If you do that, the method name is usually enough to pinpoint the location of the exception. I realize that is not always an option, but it is worth considering.
How to get the classes that are available in a '.cs' file.? Like we can get the classes and methods in an Assembly using,
Assembly.GetTypes() and Type.GetMethods()
to get the Class and methods in an Assembly.
Similarly how to get all the classes present within a C# file(.cs file).? I need to get the classes in a .cs file from which i can easily get the methods within them and further details like parameters of methods etc.
Short of using a C# parser, there's no direct way of doing it. You could compile the .cs file using CSharpCodeProvider (which only works if the file compiles on its own and you can tell all the referenced assemblies to the compiler) and use reflection on the resulting assembly.
I recommend you to use a parser generator tool to generate a quick c# parser, you can use Antlr.
Also you can check this and this
The compiler erases all notions of a codefile from your code as it is compiled. That being said perhaps it is possible to retrieve the information you want from debugging symbols if they are available in your assembly.
From with in the class you can always call
this.GetType()
or outside the class you can always call
obj.GetType()
however when you compile an application, which is required for reflection to work, you can no longer get their definitions by file.
I've done this previously by invoking the C# compiler, compiling the C# file and then using reflection on the outputted type. This is possible if the C# file is a standalone file and doesn't have any dependencies.
However, the correct way would be to use a parser - something which isn't that easy to do. There are a couple of options available, MinosseCC being one of them.
Incidentally, C# 5.0 will make it a lot easier to compile code on the fly by being able to compile a String and getting back executable code. Can't wait for this - it's sure to confuse everyone that reads my code.
First of all, there is no such thing as the .cs file in which a class is defined. A class can be marked as partial and parts can be defined in several .cs files.
When you compile with debug information, the filenames for each method remain in the assembly (for each line of the source file, the corresponding IL commands are tagged).
Unfortunately, I don't know an easy way to get to that information from within the running application (without parsing the assembly file manually).
If you are safe calling the method, you can call it and in parallel construct a stack trace (from another thread) - in the StackFrame object you will find the original file name. But this is slow (as you have to call every method just to find that the filename is different) and risky (what if the method formats your hard drive?).
So, the only way you could go is try to parse the .cs file with a parser like AntLR yourself.