2008-10-01 62 views
35

Tôi đang cố gắng thêm một trình xử lý ngoại lệ chưa được xử lý trong .net (C#) cần trợ giúp cho 'người dùng' càng tốt. Người dùng cuối chủ yếu là các lập trình viên nên họ chỉ cần một gợi ý về đối tượng nào họ đang thao tác sai.Trong trường hợp ngoại lệ .net cách lấy một stacktrace với các giá trị đối số

Tôi đang phát triển một cửa sổ tương tự như báo cáo lỗi Windows XP khi một ứng dụng gặp sự cố nhưng cung cấp càng nhiều thông tin bắt chước càng tốt về ngoại lệ được ném.

Khi theo dõi ngăn xếp cho phép tôi (vì tôi có mã nguồn) để xác định nguồn gốc của sự cố, người dùng không có nó và do đó họ bị mất mà không có thêm thông tin. Không cần phải nói tôi phải dành nhiều thời gian hỗ trợ công cụ.

Có một vài ngoại lệ hệ thống như KeyNotFoundException được ném bởi bộ sưu tập từ điển thực sự gây lỗi cho tôi vì chúng không bao gồm trong thông báo khóa không tìm thấy. Tôi có thể điền vào mã của tôi với tấn cố gắng bắt khối nhưng nó khá agressive và rất nhiều mã để duy trì, chưa kể đến một tấn nhiều dây mà phải kết thúc được bản địa hoá.

Cuối cùng câu hỏi: Có cách nào để có được (lúc chạy) các giá trị của các đối số của từng hàm trong theo dõi ngăn xếp cuộc gọi không? Điều đó một mình có thể giải quyết 90% các cuộc gọi hỗ trợ.

+1

Điều này đã được trả lời tốt, nhưng để tham khảo trong tương lai tôi cũng muốn thêm một con trỏ vào bài viết blog tuyệt vời của Raymond Chen [Khi nào một đối tượng trở nên sẵn sàng để thu thập rác?] (Http: //blogs.msdn. com/b/oldnewthing/archive/2010/08/10/10048149.aspx) Trong số những thứ khác, nó chỉ ra rằng việc thu thập đáng tin cậy các giá trị đối số từ dấu vết ngăn xếp là không thể, vì các đối số có thể được thu thập trong khi các phương thức được tham chiếu vẫn đang thực thi . –

+0

Tôi đã thấy https://stackoverflow.com/questions/2696691/can-i-get-the-method-local-variables-through-a-stack-trace-in-c nhưng tôi không biết cách để có được 'StackTrace' từ đối tượng' Exception'. Trên nó có một 'String'. –

Trả lời

0

Tôi không biết bất cứ điều gì như thế, nhưng đã tự mình muốn. Tôi thường tự làm điều đó khi ném ngoại lệ, nhưng nếu nó không phải là của bạn để ném, sau đó bạn có thể được ra với phần còn lại của chúng tôi.

1

Tôi không tin rằng có một cơ chế tích hợp sẵn. Truy xuất từng khung của dấu vết ngăn xếp, trong khi cho phép bạn xác định phương thức trong dấu vết, chỉ cung cấp cho bạn thông tin kiểu được phản ánh trên phương thức đó. Không có thông tin tham số. Tôi nghĩ rằng đây là lý do tại sao một số ngoại lệ, đáng chú ý là ArgumentException, et. al. cung cấp một cơ chế để xác định giá trị của đối số liên quan đến ngoại lệ vì không có cách nào dễ dàng để có được nó.

7

Tôi không nghĩ System.Diagnostics.StackFrame cung cấp thông tin đối số (ngoài chữ ký phương thức).

Bạn có thể thực hiện các cuộc gọi phiền hà với ghi nhật ký theo dõi qua AOP hoặc thậm chí sử dụng các tính năng chặn ngoại lệ của nó để đăng nhập có điều kiện mà không phải xả mã của bạn. Có một cái nhìn xung quanh http://www.postsharp.org/.

0

Tôi không biết cách lấy giá trị của đối số của từng hàm trong theo dõi ngăn xếp cuộc gọi, nhưng một giải pháp là bắt ngoại lệ cụ thể (KeyNotFoundException trong ví dụ của bạn) và ném lại Ngoại lệ mới. Cho phép bạn liên kết bất kỳ thông tin bổ sung mà bạn muốn

Ví dụ:

Dim sKey as String = "some-key" 
Dim sValue as String = String.Empty 

Try 
    sValue = Dictionary(sKey) 
Catch KeyEx As KeyNotFoundException 
    Throw New KeyNotFoundException("Class.Function() - Couldn't find [" & sKey & "]", KeyEx) 
End Try 

Tôi đánh giá cao tuyên bố của bạn về khoanh vùng các dây lỗi, nhưng nếu khán giả của bạn là 'chủ yếu là lập trình viên' sau đó ước đã đưa ra một mô hiểu tiếng Anh Ở một mức độ nào đó (đúng hoặc sai - nhưng đó là một cuộc tranh luận khác!)

+1

Vâng, tôi biết tôi có thể, nhưng đó là một cách tuyệt vời những gì tôi đang cố tránh. Cuối cùng tôi đã làm cho tôi có khoảng 200 cuộc gọi đến hashtables và họ sẽ increasse hàng ngày. Tôi nghĩ về một hàm trợ giúp nhưng nó vẫn trông xấu xí và chỉ giải quyết KeyNotFoundException. – Caerbanog

+1

Có thể một chức năng trợ giúp là cách để đi, xin lỗi tôi không thể giúp đỡ (thêm vào yêu thích của tôi để tôi có thể kiểm tra lại để xem những gì bạn quyết định): o) – Andrew

1

Vì người dùng cuối là nhà phát triển, bạn có thể cung cấp cho họ phiên bản cho phép ghi nhật ký tất cả các giá trị/đối số chính. Và cung cấp một cơ sở để họ có thể bật/tắt đăng nhập.

0

Khi bạn có ngoại lệ, hai điều bạn quan tâm là System.Diagnostics.StackTrace và System.Diagnostics.StackFrame

Có một ví dụ MSDN here

+0

Ok, nhưng khi tôi có 'Exception' tôi don không thấy một cách để có được đối tượng 'StackTrace'. 'StackTrace' trong trường hợp ngoại lệ là một biểu diễn Chuỗi đã được tuần tự hóa của ngăn xếp cuộc gọi. –

+0

@CsabaToth https://msdn.microsoft.com/en-us/library/4ce0ktkk(v=vs.110).aspx – slf

+0

bạn có nghĩa là tôi nên xây dựng đối tượng 'StackTrace' sử dụng ngoại lệ làm tham số hàm tạo? Tôi đoán tôi sẽ thử rằng –

3

Đáng tiếc là bạn không thể có được những giá trị thực tế của thông số từ callstack trừ trường hợp công cụ gỡ lỗi thực sự gắn liền với ứng dụng. Tuy nhiên bằng cách sử dụng đối tượng StackTrace và StackFrame trong System.Diagnostics bạn có thể đi bộ ngăn xếp cuộc gọi và đọc tất cả các phương thức được gọi và tên và kiểu tham số. Bạn sẽ làm như sau:

System.Diagnostics.StackTrace callStack = new System.Diagnostics.StackTrace(); 
System.Diagnostics.StackFrame frame = null; 
System.Reflection.MethodBase calledMethod = null; 
System.Reflection.ParameterInfo [] passedParams = null; 
for (int x = 0; x < callStack.FrameCount; x++) 
{ 
    frame = callStack.GetFrame(x); 
    calledMethod = frame.GetMethod(); 
    passedParams = calledMethod.GetParameters(); 
    foreach (System.Reflection.ParameterInfo param in passedParams) 
     System.Console.WriteLine(param.ToString()); 
} 

Nếu bạn cần giá trị thực tế thì bạn sẽ cần phải lấy minidumps và phân tích chúng tôi sợ. Thông tin về việc thông tin bãi có thể được tìm thấy tại địa chỉ:

http://www.debuginfo.com/tools/clrdump.html

+4

Vấn đề với điều này là bạn đang nhận được ngăn xếp từ bên trong Catch, không phải là ngăn xếp tại thời điểm ngoại lệ. – GeekyMonkey

1

nó là về mặt lý thuyết có thể làm những gì bạn muốn bằng cách tận dụng các định dạng thực thi (PE) tập tin di động để có được các loại biến và bù đắp, nhưng tôi chạy vào một [tài liệu] tường cố gắng để làm điều này một vài năm trước đây. Chúc may mắn!

1

Nếu bạn có thể làm những gì bạn đang tìm kiếm, bạn sẽ đánh bại một phần không thể tách rời của bảo mật .NET.

Tùy chọn tốt nhất trong trường hợp, nó để đính kèm vào trình gỡ lỗi hoặc trình thu thập thông tin (một trong hai người có thể truy cập các giá trị đó). Trước đây có thể được đính kèm, sau này cần phải được hoạt động trước khi chương trình bắt đầu.

+1

+1 để đề cập đến một vấn đề thú vị (bảo mật); nhưng bạn có thể xây dựng thêm một chút về cách thức này sẽ phá vỡ an ninh, hay đúng hơn, tại sao bạn xem xét khía cạnh "không thể thiếu" đó? – stakx

5

Tương tự như vậy, tôi không tìm thấy bất kỳ thứ gì để lấy được các thông số tự động khi chạy. Thay vào đó, tôi đã sử dụng một Visual Studio add-in để tạo ra mã mà rõ ràng gói lên các thông số, như thế này:

public class ExceptionHandler 
{ 
    public static bool HandleException(Exception ex, IList<Param> parameters) 
    { 
     /* 
     * Log the exception 
     * 
     * Return true to rethrow the original exception, 
     * else false 
     */ 
    } 
} 

public class Param 
{ 
    public string Name { get; set; } 
    public object Value { get; set; } 
} 

public class MyClass 
{ 
    public void RenderSomeText(int lineNumber, string text, RenderingContext context) 
    { 
     try 
     { 
      /* 
      * Do some work 
      */ 
      throw new ApplicationException("Something bad happened"); 
     } 
     catch (Exception ex) 
     { 
      if (ExceptionHandler.HandleException(
        ex, 
        new List<Param> 
        { 
         new Param { Name = "lineNumber", Value=lineNumber }, 
         new Param { Name = "text", Value=text }, 
         new Param { Name = "context", Value=context} 
        })) 
      { 
       throw; 
      } 
     } 
    } 
} 

EDIT: hoặc cách khác, bằng cách làm cho tham số để HandleException một mảng params:

public static bool HandleException(Exception ex, params Param[] parameters) 
{ 
    ... 
} 

... 
if (ExceptionHandler.HandleException(
        ex, 
        new Param { Name = "lineNumber", Value=lineNumber }, 
        new Param { Name = "text", Value=text }, 
        new Param { Name = "context", Value=context} 
        )) 
{ 
    throw; 
} 
... 

Đó là một chút đau đớn khi tạo mã bổ sung để chuyển các tham số tới trình xử lý ngoại lệ một cách rõ ràng, nhưng với việc sử dụng phần bổ trợ, ít nhất bạn cũng có thể tự động hóa nó.

Một thuộc tính tùy chỉnh có thể được sử dụng để chú thích bất kỳ thông số mà bạn không muốn add-in để vượt qua để xử lý ngoại lệ:

public UserToken RegisterUser(string userId, [NoLog] string password) 
{ 
} 

EDIT 2ND:

Tâm trí bạn, tôi d hoàn toàn quên về AVICode:

http://www.avicode.com/

Họ sử dụng kỹ thuật chặn cuộc gọi để cung cấp chính xác loại thông tin này, vì vậy nó phải có thể.

2

Có một công cụ phần mềm từ redgate, có vẻ rất promissing.

http://www.red-gate.com/products/dotnet-development/smartassembly/

Hiện nay chúng tôi đang thu thập báo cáo lỗi khách hàng của chúng tôi qua email và đôi khi tôi phải vật lộn với một số dữ liệu quan trọng bị mất tích (chủ yếu là một số biến rất cơ bản, như id từ kỷ lục hiện tại vì vậy tôi có thể tái tạo các lỗi). Tôi chưa thử nghiệm công cụ này, nhưng từ sự hiểu biết của tôi nó làm những gì thu thập các giá trị đối số và biến địa phương từ ngăn xếp.

Các vấn đề liên quan