如何使用try-catch获取代码的错误行数

时间:2011-12-01 08:39:17

标签: c# exception

我想获取导致错误的代码行数。例如;

static void Main(string[] args)
{
    using (SqlConnection conn = new SqlConnection(bagcum))
    {
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "DONTINSERT into GIVEMEERROR(CamNo,Statu) values (" + 23 + "," + 0 + ")";
        conn.Open();
        int n = cmd.ExecuteNonQuery();
    }
}

所以我们知道代码不起作用,它会抛出异常代码行号:

int n = cmd.ExecuteNonQuery();

那么如何获得使用try-catch的行号?我尝试使用StackTrace类但它的行号为0:

static void Main(string[] args)
{
    try
    {
        using (SqlConnection conn = new SqlConnection(bagcum))
        {
            SqlCommand cmd = conn.CreateCommand();
            cmd.CommandText = "DONTINSERT into GIVEMEERROR(CamNo,Statu) values (" + 23 + "," + 0 + ")";
            conn.Open();
            int n = cmd.ExecuteNonQuery();
        }        
    }
    catch (Exception ex)
    {
        System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);            
        Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
    }
}

输出:

Line:0

更新
通常错误的代码行是22,所以我必须得到这个数字。

由于

10 个答案:

答案 0 :(得分:21)

尝试这个简单的黑客:

首先将此(扩展)类添加到命名空间(大多数是顶级类):

public static class ExceptionHelper
{
    public static int LineNumber(this Exception e)
    {

        int linenum = 0;
        try
        {
            //linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(":line") + 5));

            //For Localized Visual Studio ... In other languages stack trace  doesn't end with ":Line 12"
            linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(' ')));

        }


        catch
        {
            //Stack trace is not available!
        }
        return linenum;
    }
}

完成它!在需要时使用LineNumber方法:

try
{
//Do your code here
}
catch (Exception e)
{
int linenum = e.LineNumber();
}

答案 1 :(得分:9)

试试这个

要获取StackTrace中的行号,您需要在dll / exes旁边拥有正确的调试信息(PDB文件)。要生成调试信息,请在Project Properties -> Build -> Advanced -> Debug Info中设置选项:

alt text

将其设置为full就足够了(有关其他选项的作用,请参阅MSDN docs)。默认情况下会为Debug构建配置生成调试信息(即PDB文件),但也可以为Release构建配置生成调试信息(即PDB文件)。

为发布版本生成PDB使您可以在没有PDB的情况下发送代码,但是如果需要行号(甚至连接远程调试器),则将PDB放在dll旁边。需要注意的一点是,在发布版本中,由于编译器或JIT编译器的优化,行号可能不完全正确(如果行号显示为0,则尤其如此)。

答案 2 :(得分:7)

问题在于您正在尝试获取异常的第一帧的行号:

System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());

但是,的异常源自您编写的行ExecuteNonQuery,但在该函数内的某处,可能是多个堆栈帧(即嵌套函数调用)更深。因此,第一帧(使用GetFrame(0)明确检索的)位于Microsoft的代码中(很可能是System.Data.dll),您没有任何调试符号。

在函数中写出完整的异常堆栈跟踪,看看我的意思:

try
{
   // your code ...
}
catch (Exception ex) 
{
   Console.WriteLine(ex);
}

如果没有解析堆栈跟踪(即ex.StackTrace),就没有可靠的原因来获取“ExecuteNonQuery()”调用的编号。我特别尝试将堆栈帧计算在你对ExecuteNonQuery()的调用发生的堆栈中。

我想知道,你需要什么样的唯一的亚麻布,为什么不只是记录/打印/无论完整的堆栈跟踪。至少出于诊断原因,无论如何都要有用。

答案 3 :(得分:5)

如果未初始化StackTrace以包含fileinfo,则结果可能为0。

enter image description here

试试这个

try
{
    //code
}
catch (Exception e)
{
    var lineNumber = new System.Diagnostics.StackTrace(e, true).GetFrame(0).GetFileLineNumber();
}

这对我有用。

答案 4 :(得分:4)

您可以使用System.Diagnostics.StackTrace课程,如下所示:

public void MethodName()
{
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        // Get stack trace for the exception with source file information
        var trace = new StackTrace(ex, true);

        // Get the top stack frame
        var frame = trace.GetFrame(0);

        // Get the line number from the stack frame
        var line = frame.GetFileLineNumber();
    }
}

答案 5 :(得分:4)

这是从Exception对象获取大量信息的一种相当简单的方法:只需将这样的代码添加到任何可能抛出异常的方法中:

catch (Exception ex)
{
    String exDetail = String.Format(ExceptionFormatString, ex.Message, Environment.NewLine, ex.Source, ex.StackTrace);
    MessageBox.Show(exDetail);
}

您获得的信息通常会更具体,特别是关于出现问题的行号,而不是您看到的信息。

你可能已经注意到String.Format()使用了一个常量,即" ExceptionFormatString"。这是一个很好的做法,所以如果你想改变它,在将上面的代码添加到40-11方法之后,你可以把它改成一个地方。无论如何,这是:

public static readonly String ExceptionFormatString = "Exception message: {0}{1}Exception Source: {2}{1}Exception StackTrace: {3}{1}";

快乐调试!

答案 6 :(得分:1)

要获取行号,您需要应用程序处于调试模式,在同一文件夹(.pdb文件)中包含调试符号,以显示行号。您发布的代码应该可以正常工作。

答案 7 :(得分:0)

以下代码异常日志处理程序方法正常工作:

抓住

中的

 catch (Exception ex)
            {
                CommonTools.vAddToLog(ex, EmpID, ErrorCodes.UnDefined);
                Response.Redirect("~/ErrorPage.aspx");
            }
AddToLog 方法中的

 string _exMsgErr = string.Empty;
                var frame = oStackTrace.FrameCount > 1 ? oStackTrace.GetFrame(1) : oStackTrace.GetFrame(0);
                if (oException.GetType() == typeof(JOVALException))
                {
                    JOVALException _JOVALEx = (JOVALException)oException;
                    _exMsgErr = _JOVALEx.Message;
                }
                else
                {
                    _exMsgErr = oException.Message;
                }
                ErrorLog oError = new ErrorLog(frame.GetMethod().Name, (string)frame.GetFileName(), (int)frame.GetFileLineNumber(), sCustomErrorMessage == string.Empty ? _exMsgErr : sCustomErrorMessage, sUserID, oErrCode);
                //Cont. your code of log file

最后,xml日志文件如下所示:

<ErrorLog>
<MethodName>FillRolesDDLs</MethodName>
<FileName>
F:\Projects\ERP\ERP\Pages\SystemSettings\Roles.aspx.cs
</FileName>
<LineNumber>61</LineNumber>
<ErrorMesssage>
The given DataRow is not in the current DataRowCollection.
</ErrorMesssage>
<UserID>1</UserID>
<ErrCode>UnDefined</ErrCode>
<Time>15/03/2015 16:23:21.976</Time>
</ErrorLog>

答案 8 :(得分:0)

在.NET 4.5中,您可以使用ExceptionDispatchInfo重新抛出异常而不是经典// Check for login status when changing page URL $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { var currentRoute = toState.name; $rootScope.authenticated = false; if ($auth.isAuthenticated()) { $rootScope.authenticated = true; } (确保PDB文件存在或不显示行号):

throw;

来源:blogpost。 Windows上的PDB文件don't decrease performance

答案 9 :(得分:-1)

使用可以抛出的try / catch将整个堆栈跟踪复制到字符串或字符串构建器中,请参阅下面的示例

try
{
    //Do some programming
}
catch(Exception ex)
{

   //Catch the exception and assign the stack trace
   StackTrace = ex;
}

输出

System.IndexOutOfRangeException: Index was outside the bounds of the array.   
at Program.Run() in C:\Console Application1\Program.cs:line 37    
at Program.Main(String[] args) in C:\Console Application1\Program.cs:line 45 

第一行显示异常的类型和消息。第二行显示抛出异常的文件,函数和行号