C#-调用异常时如何获取类名和行号
我需要两个方法,一个用于获取调用异常的类,另一个用于获取调用异常的行号 到目前为止,我已经有了这段代码,它将类名和行号放在一起(例如:DatabaseHandler.cs:Line 70): 这是在特定数据库异常时返回的内容。触发时没有行号或类名。我怎么能得到这个C#-调用异常时如何获取类名和行号,c#,asp.net,C#,Asp.net,我需要两个方法,一个用于获取调用异常的类,另一个用于获取调用异常的行号 到目前为止,我已经有了这段代码,它将类名和行号放在一起(例如:DatabaseHandler.cs:Line 70): 这是在特定数据库异常时返回的内容。触发时没有行号或类名。我怎么能得到这个 Error was found at Class: Oracle.DataAccess.Client.OracleException. Line Number: 0 我想要的是例如:“Class:Loggi
Error was found at Class: Oracle.DataAccess.Client.OracleException.
Line Number: 0
我想要的是例如:“Class:Logging.cs,第57行”
谢谢,
Ryan系统.环境.堆栈跟踪。任何时候都有用,而不仅仅是在例外情况下。可能需要一些字符串操作来使用它 如果您更喜欢高科技产品,可以使用
System.Diagnostics.StackFrame
;查看对象浏览器的全部详细信息,但它有查找文件名、行号和列号等的方法。您可以这样做
try
{
// Some code that can cause an exception.
throw new Exception("An error has happened");
}
catch (Exception ex)
{
System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
Console.WriteLine(trace.GetFrame(0).GetMethod().ReflectedType.FullName);
Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
Console.WriteLine("Column: " + trace.GetFrame(0).GetFileColumnNumber());
}
我正在使用以下
类DebugE
跟踪应用程序中的异常并记录内容:它输出线程#DateTime、ClassName.MethodName、行和列编号以及异常消息
using System;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Text.RegularExpressions;
namespace YourApp
{
class DebugE
{
public static void d(Exception e)
{
try
{
MethodBase site = e.TargetSite;//Get the methodname from the exception.
string methodName = site == null ? "" : site.Name;//avoid null ref if it's null.
methodName = ExtractBracketed(methodName);
StackTrace stkTrace = new System.Diagnostics.StackTrace(e, true);
for (int i = 0; i < 3; i++)
{
//In most cases GetFrame(0) will contain valid information, but not always. That's why a small loop is needed.
var frame = stkTrace.GetFrame(i);
int lineNum = frame.GetFileLineNumber();//get the line and column numbers
int colNum = frame.GetFileColumnNumber();
string className = ExtractBracketed(frame.GetMethod().ReflectedType.FullName);
Trace.WriteLine(ThreadAndDateInfo + "Exception: " + className + "." + methodName + ", Ln " + lineNum + " Col " + colNum + ": " + e.Message);
if (lineNum + colNum > 0)
break; //exit the for loop if you have valid info. If not, try going up one frame...
}
}
catch (Exception ee)
{
//Avoid any situation that the Trace is what crashes you application. While trace can log to a file. Console normally not output to the same place.
Console.WriteLine("Tracing exception in d(Exception e)" + ee.Message);
}
}
public static void d(string str)
{
try
{
StackFrame frame = new StackFrame(1);
var method = frame.GetMethod();
string name = ExtractBracketed(method.Name);//extract the content that is inside <brackets> the rest is irrelevant
Trace.WriteLine(ThreadAndDateInfo + method.DeclaringType + "." + name + ": " + str);
}
catch (Exception e)
{
Console.WriteLine("Tracing exception in d(string str)" + e.Message);
}
}
private static string ExtractBracketed(string str)
{
string s;
if (str.IndexOf('<') > -1) //using the Regex when the string does not contain <brackets> returns an empty string.
s = Regex.Match(str, @"\<([^>]*)\>").Groups[1].Value;
else
s = str;
if (s == "")
return "'Emtpy'"; //for log visibility we want to know if something it's empty.
else
return s;
}
public static string ThreadAndDateInfo
{
//returns thread number and precise date and time.
get { return "[" + Thread.CurrentThread.ManagedThreadId + " - " + DateTime.Now.ToString("dd/MM HH:mm:ss.ffffff") + "] "; }
}
}
}
要将其用于普通日志记录,请调用DebugE.d(“一些文本”)代码>
它将返回相同的,但不包含行号和列号。
请注意,对于生产应用程序我总是系统地调用一个“更简单”的调用:
无效调试(string methodName,异常e)
这是因为上面的“更好”解决方案并不总是向我返回正确的方法信息。如果我的猜测是正确的,那么如果您的异常发生在一个方法中,该方法没有
try-catch
,但被另一个具有“try-catch”的方法调用,则会出现这种情况。如果这是唯一的原因,你可以说“我会添加适当的尝试捕捉”。问题是,在现实生活中,你会遇到一个真正的问题,一个真正的日志需要分析。当您注意到不相关或不充分的方法信息时,您没有机会返回代码,添加try/catch并快速复制异常。您只需处理缺少的信息就可以了…
当前改进的方法深入挖掘了几个帧,试图绕过这个问题,并在这些特殊情况下检索类、行和列。它可能看起来像这样(第三帧上的跟踪实际上返回了一个有效的名称和行号):[1-21/11 14:37:50.424914]异常:System.Threading.Tasks.Task.Delay,Ln 0列0:该值需要以毫秒为单位转换为-1(表示无限超时)、0或小于或等于Int32.MaxValue的正整数。
参数名称:延迟
[1-21/11 14:37:50.425914]异常:System.Threading.Tasks.Task.Delay,Ln 0列0:该值需要以毫秒为单位转换为-1(表示无限超时)、0或小于或等于Int32.MaxValue的正整数。
参数名称:延迟
[1-21/11 14:37:50.426415]异常:ScheduleAction.Delay,Ln 156第17列:该值需要以毫秒为单位转换为-1(表示无限超时)、0或小于或等于Int32.MaxValue的正整数。
参数名称:delay
我仍然不确定如何使用Environment.StackTrace获取类。请提供获取类的示例您是指特定实例吗?如果是这样,我认为那是不可能的。相信我,我已经试过了。如果你指的是类型,那么你可以在StackFrame
@Flnn1179上使用GetMethod().DeclaringType
方法-没关系,多亏了第二篇文章,我知道你想说什么,请查看上面的更新2。我目前正在测试它,因为我在代码的其他部分遇到了一些错误。@Flnn1179-它没有完全按照我的预期工作,有没有更好的方法?查看我的更新以获取输出+代码我想,您没有Oracle.DataAccess.Client的源文件,或者是带有/OPTIMIZE选项的发布版本。所以,你不能从中得到任何进一步的信息。你知道吗?这就是一个例子。要将跟踪打印到文件中,请将此添加到您的配置:
它对我有效,但在进行一些调整后(我使用的是Compact Framework 3.9):-Frame.GetFileLineNumber运行,但始终会导致异常。我把它拿走了所考虑的帧级别取决于调用堆栈。在我的例子中,我必须考虑GETFrAMP(1),因为我必须绕过对我的日志()函数的调用。
try
{
// Some code that can cause an exception.
throw new Exception("An error has happened");
}
catch (Exception ex)
{
System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
Console.WriteLine(trace.GetFrame(0).GetMethod().ReflectedType.FullName);
Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
Console.WriteLine("Column: " + trace.GetFrame(0).GetFileColumnNumber());
}
using System;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Text.RegularExpressions;
namespace YourApp
{
class DebugE
{
public static void d(Exception e)
{
try
{
MethodBase site = e.TargetSite;//Get the methodname from the exception.
string methodName = site == null ? "" : site.Name;//avoid null ref if it's null.
methodName = ExtractBracketed(methodName);
StackTrace stkTrace = new System.Diagnostics.StackTrace(e, true);
for (int i = 0; i < 3; i++)
{
//In most cases GetFrame(0) will contain valid information, but not always. That's why a small loop is needed.
var frame = stkTrace.GetFrame(i);
int lineNum = frame.GetFileLineNumber();//get the line and column numbers
int colNum = frame.GetFileColumnNumber();
string className = ExtractBracketed(frame.GetMethod().ReflectedType.FullName);
Trace.WriteLine(ThreadAndDateInfo + "Exception: " + className + "." + methodName + ", Ln " + lineNum + " Col " + colNum + ": " + e.Message);
if (lineNum + colNum > 0)
break; //exit the for loop if you have valid info. If not, try going up one frame...
}
}
catch (Exception ee)
{
//Avoid any situation that the Trace is what crashes you application. While trace can log to a file. Console normally not output to the same place.
Console.WriteLine("Tracing exception in d(Exception e)" + ee.Message);
}
}
public static void d(string str)
{
try
{
StackFrame frame = new StackFrame(1);
var method = frame.GetMethod();
string name = ExtractBracketed(method.Name);//extract the content that is inside <brackets> the rest is irrelevant
Trace.WriteLine(ThreadAndDateInfo + method.DeclaringType + "." + name + ": " + str);
}
catch (Exception e)
{
Console.WriteLine("Tracing exception in d(string str)" + e.Message);
}
}
private static string ExtractBracketed(string str)
{
string s;
if (str.IndexOf('<') > -1) //using the Regex when the string does not contain <brackets> returns an empty string.
s = Regex.Match(str, @"\<([^>]*)\>").Groups[1].Value;
else
s = str;
if (s == "")
return "'Emtpy'"; //for log visibility we want to know if something it's empty.
else
return s;
}
public static string ThreadAndDateInfo
{
//returns thread number and precise date and time.
get { return "[" + Thread.CurrentThread.ManagedThreadId + " - " + DateTime.Now.ToString("dd/MM HH:mm:ss.ffffff") + "] "; }
}
}
}
catch (Exception e)
{
DebugE.d(e);
}