2011-12-01 1426 views
24

我想獲取導致錯誤的代碼行號。例如;如何使用try-catch獲取代碼的錯誤行數

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()); 
    } 
} 

OUTPUT:

Line:0 

更新:
通常的代碼錯誤行是22,所以我必須得到這個數字。

感謝

+0

如果你處於'RELEASE'模式,行號(除其他之外)不再是堆棧跟蹤。在DEBUG模式下編譯的最簡單方法。如果它仍然不起作用,請檢查*項目屬性\高級\調試信息*中是否有完整的調試信息。 –

+0

@JiBéDoublevé它處於調試模式,並且已完全調試 –

+1

您的.pdb文件與所有其他文件位於同一目錄中嗎? –

回答

18

試試這個簡單的黑客,而不是:

首先加入這個(擴展)類的命名空間(大多數是頂層類):

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

複製中使用try/catch語句可以拋出一個字符串或StringBuilder的整個堆棧跟蹤,看看下面的例子

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 

第一行顯示異常和消息的類型。第二行顯示引發異常的文件,函數和行號

+0

以及這似乎是一個解決方案,但我要求不解析任何輸出 –

+0

沒有足夠的代碼,我不能得到StackTrace = ex;上班。 -1爲非工作示例。 – Omzig

1

要獲得行號,需要將應用程序設置爲調試模式將調試符號包含在同一文件夾中(.pdb文件)出現行號。你代碼發佈後應該工作。

7

試試這個

要在堆棧跟蹤獲得的行號,你需要有正確的調試信息(PDB文件)旁邊的的DLL/EXE文件。要生成調試信息,設置在Project Properties -> Build -> Advanced -> Debug Info選項:

alt text

將其設置爲full應該足夠了(見MSDN docs什麼其他選擇呢)。調試信息(即PDB文件)默認爲Debug版本配置生成,但也可以爲Release版本配置生成。

爲發佈版本生成PDB使您可以在沒有PDB的情況下發送代碼,但如果需要行號(甚至連接遠程調試器),則可以將PDB放在dll旁邊。需要注意的一點是,在發佈版本中,由於編譯器或JIT編譯器進行優化,行號可能並不完全正確(如果行號顯示爲0,尤其如此)。

6

的問題是,你想要得到的異常的第一幀的行號:

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()發生的堆棧上的堆棧幀。

然而,我想知道,你需要什麼唯一的linenumber爲什麼不只是登錄/打印/不管完整的stacktrace。至少出於診斷的原因,無論如何,這都是非常有用的。

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(); 
    } 
} 
+1

謝謝,但它不工作,行= 0再次 –

3

如果您未初始化StackTrace以包含fileinfo,您可能會得到0結果。

enter image description here

試試這個

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

這爲我工作。

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> 
2

這是一個相當簡單的方法來得到一堆從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}"; 

快樂調試!

+0

這應該是接受answ.er – GunWanderer

0

在.NET 4.5,你可以使用ExceptionDispatchInfo重新拋出的異常,而不是經典throw;(確保PDB文件是有或沒有行號會顯示):

static void A() 
    { 
     try 
     { 
      throw new Exception("A"); 
     } 
     catch (Exception e) 
     { 
      ExceptionDispatchInfo.Capture(e).Throw(); 
     } 
    } 

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