2010-09-20 28 views
8

Im tìm cách tạo các tệp minidump trong các ứng dụng của tôi mô phỏng với những gì ProcDump thực hiện nhưng có thể đặt trước bằng mã và không phải trích xuất công cụ 3dparty để thực hiện.Tạo/tạo các tệp mdump trong ứng dụng của tôi

Lý do chính không muốn sử dụng ProcDump là:
1) Kích thước của tệp nhị phân sẽ tăng lên rất nhiều (Đây là vấn đề vì ứng dụng của tôi là phần mềm miễn phí và băng thông không miễn phí).
2) Cảm thấy bẩn.
3) Không có cách nào tôi có thể chuyển ứng dụng đó để chạy các cửa sổ trên thiết bị di động.

Yêu cầu của tôi là:
1) Khả năng tạo tệp mdump trong một vụ tai nạn nghiêm trọng.
2) Có khả năng làm "tạm dừng" ứng dụng thực hiện một bãi chứa, và contiune sẽ là một tiền thưởng
.
Nếu điều này không thực sự là một tùy chọn, có cách nào để nhận giá trị của biến số cục bộ trong ngữ cảnh hiện tại không?

Lưu ý phụ: Tôi viết bài này, nhưng nó rất cũ nên tôi rất do dự để làm cơ sở cho công việc của tôi.
Dường như có vấn đề với IE 9 hoặc với trang web, vì vậy tôi gặp sự cố với thẻ.

+0

thức bất kỳ giải pháp tốt về vấn đề này? với mã nguồn ứng dụng mẫu tốt trong .NET? – Kiquenet

Trả lời

6

Vì vậy, có một giải pháp mà nói đến cái tâm và đáp ứng các mục tiêu sau:

  • Kích thước của hệ nhị phân sẽ tăng khoảng 300k
  • Khả năng tạo tệp mdump trong một vụ tai nạn nghiêm trọng.
  • Có khả năng làm "tạm dừng" ứng dụng làm một bãi chứa, và contiune sẽ là một tiền thưởng

tôi sẽ cung cấp cho yêu cầu này một ẩn số đầy đủ:

  • Không có cách nào tôi có thể cổng mà ứng dụng để chạy các cửa sổ trên thiết bị di động.

Vậy giải pháp là gì?

Tích hợp các phần bắt buộc bạn cần từ Mẫu Microsoft cho MDbg.exe để cung cấp cho bạn trình gỡ lỗi 'just-in-time' đính kèm, đổ và detaches khỏi quá trình crashing.

Bước 1 - Bắt đầu bằng cách tải về mã nguồn để các mdbg từ đây: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=38449a42-6b7a-4e28-80ce-c55645ab1310&DisplayLang=en

Bước 2 - Tạo một handler 'tai nạn' mà sinh ra một quá trình gỡ lỗi và chờ đợi để hoàn tất. Tôi đã sử dụng một vài dòng mã sau để khởi động lại cùng một exe với một vài đối số bổ sung để gọi trình gỡ lỗi và xuất tệp xml thành std :: out.

string tempFile = Path.GetTempFileName(); 
Mutex handle = new Mutex(true, typeof(Program).Namespace + "-self-debugging"); 
try 
{ 
    Process pDebug = Process.Start(typeof(Program).Assembly.Location, 
     "debug-dump " + Process.GetCurrentProcess().Id + " " + tempFile); 
    if (pDebug != null) 
     pDebug.WaitForExit(); 
} 
catch { } 
finally 
{ 
    handle.ReleaseMutex(); 
} 

Console.WriteLine(File.ReadAllText(tempFile)); 

Bước 3 - Viết thói quen kết xuất gỡ lỗi, điều này có thể ở cùng exe hoặc trong một exe khác. Bạn sẽ cần tham khảo (hoặc bao gồm nguồn từ) các mô đun 'thô', 'corapi' và 'mdbgeng' từ mẫu. Sau đó, thêm một vài dòng để chính bạn():

public static void Main(string[] args) 
{ 
    if (args.Length > 0 && args[0] == "debug-dump") 
    { //debug-dump process by id = args[1], output = args[2] 
     using (XmlTextWriter wtr = new XmlTextWriter(args[2], Encoding.ASCII)) 
     { 
      wtr.Formatting = Formatting.Indented; 
      PerformDebugDump(Int32.Parse(args[1]), wtr); 
     } 
     return; 
    } 
    //... continue normal program execution 
} 

static void PerformDebugDump(int process, XmlWriter x) 
{ 
    x.WriteStartElement("process"); 
    x.WriteAttributeString("id", process.ToString()); 
    x.WriteAttributeString("time", XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.RoundtripKind)); 

    MDbgEngine e = new MDbgEngine(); 
    MDbgProcess me = e.Attach(process); 
    me.Go().WaitOne(); 

    try 
    { 
     x.WriteStartElement("modules"); 
     foreach (MDbgModule mod in me.Modules) 
      x.WriteElementString("module", mod.CorModule.Name); 
     x.WriteEndElement(); 

     foreach (MDbgThread thread in me.Threads) 
     { 
      x.WriteStartElement("thread"); 
      x.WriteAttributeString("id", thread.Id.ToString()); 
      x.WriteAttributeString("number", thread.Number.ToString()); 
      int ixstack = -1; 

      foreach (MDbgFrame frame in thread.Frames) 
      { 
       x.WriteStartElement("frame"); 
       x.WriteAttributeString("ix", (++ixstack).ToString()); 
       x.WriteAttributeString("loc", frame.ToString(String.Empty)); 
       string valueText = null; 

       x.WriteStartElement("args"); 
       try 
       { 
        foreach (MDbgValue value in frame.Function.GetArguments(frame)) 
        { 
         x.WriteStartElement(value.Name); 
         x.WriteAttributeString("type", value.TypeName); 
         try { x.WriteAttributeString("value", value.GetStringValue(1, false)); } 
         finally { x.WriteEndElement(); } 
        } 
       } 
       catch { } 
       x.WriteEndElement(); 

       x.WriteStartElement("locals"); 
       try 
       { 
        foreach (MDbgValue value in frame.Function.GetActiveLocalVars(frame)) 
        { 
         x.WriteStartElement(value.Name); 
         x.WriteAttributeString("type", value.TypeName); 
         try { x.WriteAttributeString("value", value.GetStringValue(1, false)); } 
         finally { x.WriteEndElement(); } 
        } 
       } 
       catch { } 
       x.WriteEndElement(); 
       x.WriteEndElement(); 
      } 
      x.WriteEndElement(); 
     } 
    } 
    finally 
    { 
     me.Detach().WaitOne(); 
    } 

    x.WriteEndElement(); 
} 

Kết quả ví dụ

<process id="8276" time="2010-10-18T16:03:59.3781465-05:00"> 
<modules> 
<module>C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll</module> 
...etc 
</modules> 
<thread id="17208" number="0"> 
<frame ix="0" loc="System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (source line information unavailable)"> 
    <args> 
     <this type="System.Windows.Forms.Application.ComponentManager" value="System.Windows.Forms.Application.ComponentManager&#xA; oleComponents=System.Collections.Hashtable&#xA; cookieCounter=1&#xA; activeComponent=System.Windows.Forms.Application.ThreadContext&#xA; trackingComponent=&lt;null&gt;&#xA; currentState=0" /> 
     <dwComponentID type="N/A" value="&lt;N/A&gt;" /> 
     <reason type="System.Int32" value="-1" /> 
     <pvLoopData type="System.Int32" value="0" /> 
    </args> 
    <locals> 
     <local_0 type="System.Int32" value="0" /> 
     <local_1 type="System.Boolean" value="True" /> 
     <local_2 type="System.Windows.Forms.UnsafeNativeMethods.IMsoComponent" value="&lt;null&gt;" /> 
     <local_3 type="N/A" value="&lt;N/A&gt;" /> 
     <local_4 type="N/A" value="&lt;N/A&gt;" /> 
     <local_5 type="N/A" value="&lt;N/A&gt;" /> 
     <local_6 type="System.Windows.Forms.Application.ThreadContext" value="System.Windows.Forms.Application.ThreadContext&#xA; contextHash=System.Collections.Hashtable&#xA; tcInternalSyncObject=System.Object&#xA; totalMessageLoopCount=1&#xA; baseLoopReason=-1&#xA; currentThreadContext=System.Windows.Forms.Application.ThreadContext&#xA; threadExceptionHandler=System.Threading.ThreadExceptionEventHandler&#xA; idleHandler=&lt;null&gt;&#xA; enterModalHandler=&lt;null&gt;&#xA; leaveModalHandler=&lt;null&gt;&#xA; applicationContext=System.Windows.Forms.ApplicationContext&#xA; parkingWindow=&lt;null&gt;&#xA; marshalingControl=System.Windows.Forms.Application.MarshalingControl&#xA; culture=&lt;null&gt;&#xA; messageFilters=&lt;null&gt;&#xA; messageFilterSnapshot=&lt;null&gt;&#xA; handle=912&#xA; id=17208&#xA; messageLoopCount=1&#xA; threadState=1&#xA; modalCount=0&#xA; activatingControlRef=&lt;null&gt;&#xA; componentManager=System.Windows.Forms.Application.ComponentManager&#xA; externalComponentManager=False&#xA; fetchingComponentManager=False&#xA; componentID=1&#xA; currentForm=Program.MainForm&#xA; threadWindows=&lt;null&gt;&#xA; tempMsg=System.Windows.Forms.NativeMethods.MSG&#xA; disposeCount=0&#xA; ourModalLoop=False&#xA; messageLoopCallback=&lt;null&gt;&#xA; __identity=&lt;null&gt;" /> 
     <local_7 type="N/A" value="&lt;N/A&gt;" /> 
     <local_8 type="N/A" value="&lt;N/A&gt;" /> 
     <local_9 type="N/A" value="&lt;N/A&gt;" /> 
     <local_10 type="N/A" value="&lt;N/A&gt;" /> 
     <local_11 type="N/A" value="&lt;N/A&gt;" /> 
     <local_12 type="N/A" value="&lt;N/A&gt;" /> 
     <local_13 type="System.Boolean" value="False" /> 
     <local_14 type="System.Windows.Forms.NativeMethods.MSG[]" value="array [1]&#xA; [0] = System.Windows.Forms.NativeMethods.MSG" /> 
    </locals> 
</frame> 
<frame ix="1" loc="System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (source line information unavailable)"> 
    <args> 
     <this type="System.Windows.Forms.Application.ThreadContext" value="System.Windows.Forms.Application.ThreadContext&#xA; contextHash=System.Collections.Hashtable&#xA; tcInternalSyncObject=System.Object&#xA; totalMessageLoopCount=1&#xA; baseLoopReason=-1&#xA; currentThreadContext=System.Windows.Forms.Application.ThreadContext&#xA; threadExceptionHandler=System.Threading.ThreadExceptionEventHandler&#xA; idleHandler=&lt;null&gt;&#xA; enterModalHandler=&lt;null&gt;&#xA; leaveModalHandler=&lt;null&gt;&#xA; applicationContext=System.Windows.Forms.ApplicationContext&#xA; parkingWindow=&lt;null&gt;&#xA; marshalingControl=System.Windows.Forms.Application.MarshalingControl&#xA; culture=&lt;null&gt;&#xA; messageFilters=&lt;null&gt;&#xA; messageFilterSnapshot=&lt;null&gt;&#xA; handle=912&#xA; id=17208&#xA; messageLoopCount=1&#xA; threadState=1&#xA; modalCount=0&#xA; activatingControlRef=&lt;null&gt;&#xA; componentManager=System.Windows.Forms.Application.ComponentManager&#xA; externalComponentManager=False&#xA; fetchingComponentManager=False&#xA; componentID=1&#xA; currentForm=Program.MainForm&#xA; threadWindows=&lt;null&gt;&#xA; tempMsg=System.Windows.Forms.NativeMethods.MSG&#xA; disposeCount=0&#xA; ourModalLoop=False&#xA; messageLoopCallback=&lt;null&gt;&#xA; __identity=&lt;null&gt;" /> 
     <reason type="System.Int32" value="-1" /> 
     <context type="System.Windows.Forms.ApplicationContext" value="System.Windows.Forms.ApplicationContext&#xA; mainForm=Program.MainForm&#xA; userData=&lt;null&gt;&#xA; ThreadExit=System.EventHandler" /> 
    </args> 
    <locals> 
     <local_0 type="System.Windows.Forms.Form" value="&lt;null&gt;" /> 
     <local_1 type="System.Boolean" value="False" /> 
     <local_2 type="N/A" value="&lt;N/A&gt;" /> 
     <local_3 type="N/A" value="&lt;N/A&gt;" /> 
     <local_4 type="N/A" value="&lt;N/A&gt;" /> 
    </locals> 
</frame> 
... etc 
</thread> 
</process> 

Vì bạn có đầy đủ sức mạnh của một debugger có gì ngăn cản bạn từ viết nhiều hay ít là như bạn thích, nhưng ví dụ trên sẽ giúp bạn bắt đầu.

CẬP NHẬT

này hoạt động với Net 2.0 và/hoặc 3.5 runtime mà không cần bất kỳ phụ thuộc hơn nữa.

Điều này có thể gỡ lỗi mã .Net 2.0/3.5 đang chạy trong quá trình .Net 4.0; tuy nhiên, nó không hoạt động với 4.0 (chưa).

Đối với 4,0 CLR xem bài này: http://blogs.msdn.com/b/rmbyers/archive/2008/10/27/icordebug-re-architecture-in-clr-4-0.aspx

+0

@ csharptest.net - Theo trang bạn đã liên kết nó yêu cầu .Net 2.0 SDK sẽ được cài đặt mà có thể không có sẵn trên máy khách. Ngoài ra, nó có hỗ trợ các chương trình .Net 4 không? – Giorgi

+0

đây là một điều thực sự cần xem xét - có thể ai đó biết các yêu cầu tối thiểu để triển khai người dùng cuối? –

+0

Mặc dù tôi chưa xác minh nhưng tôi không tin rằng có bất kỳ yêu cầu nào ngoài thời gian chạy .net. Như với net 4.0 bạn chỉ cần mẫu từ phiên bản SDK (giả sử MS đã cập nhật nó? IDK, nó thậm chí có thể làm việc vì nó là tất cả COM dựa. Tôi sẽ thử nó mà không có sdk cài đặt khi tôi nhận được để làm việc –

5

Bạn có thể gọi MiniDumpWriteDump từ AppDomain.UnhandledException hoặc Application.ThreadException trình xử lý sự kiện để tạo minidump. Bài viết này giải thích các chức năng trong các chi tiết lớn: Effective minidumps

Bạn cũng có thể sử dụng thư viện này có chức năng khác nữa: Catch All Bugs with BugTrap!

Sửa

Hình như nhận được một minidump hữu ích mà không phải là dễ dàng. Trước hết tất cả các phàn nàn sos.dll khi bãi chứa không đầy (các bãi đầy đủ khoảng 100-150MB). Thứ hai, văn bản bãi trong khối catch không được khuyến khích: Getting good dumps when an exception is thrown.

Nếu bạn có một ứng dụng winforms câu hỏi này có một số thông tin hữu ích: How does SetUnhandledExceptionFilter work in .NET WinForms applications?

+0

Im đã bẫy các Exeptions không có sẵn, nhưng tôi cần phải nhận các giá trị biến cục bộ. Và im cơ bản tìm kiếm một cách để làm điều đó năng động. Và tôi không nghĩ rằng tôi có thể tạo ra bãi chứa đầy đủ, nếu đó là lựa chọn duy nhất tôi sẽ làm điều đó, nhưng sẽ prefere minidumps có. – EKS

+0

@EKS - bạn sẽ cần đổ cho điều đó. – Giorgi

+0

Tôi nghĩ rằng, sẽ kiểm tra những gì bạn đăng vào ngày mai. Tại một bên atm lan :) – EKS

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