2009-07-15 40 views
35

Tôi biết cách tạo tệp Crash Dump với ADPlus hoặc DebugDiag, nhưng tôi tự hỏi liệu có cách nào để thực hiện điều này trên máy tính của khách hàng mà không cài đặt các công cụ này ... muốn có thể cấu hình ứng dụng của tôi (ví dụ như sử dụng một giá trị sổ đăng ký) để tạo ra một bãi chứa sự cố trong trường hợp lỗi nghiêm trọng. Cụ thể hơn, tôi cần để có thể làm điều này từ một ứng dụng C#, nhưng tôi không nhớ P/Invoke'ing nếu cần thiết. Cảm ơn!Tạo vụ tai nạn .NET tự động

Trả lời

14

Lưu ý rằng việc tạo một minidump từ bên trong quy trình "không" (hoặc thậm chí chuỗi) không phải là tầm thường hoặc có thể không chính xác (cũng là chú thích của hàm MiniDumpWriteDump). Bên cạnh đó, nếu quá trình của bạn đang trong cơn giận như vậy mà bạn có thể cần phải viết một vụ tai nạn, toàn bộ tình hình thường được hosed, mà thậm chí cố gắng để tạo ra một vụ tai nạn có thể gây ra một vụ tai nạn (tình huống như treo sang một bên - nhưng những người có thể còn khó khăn hơn để "bắt" từ trong quá trình hiện tại).

Điều "tốt nhất" bạn có thể làm, nếu bạn không thể cài đặt các ứng dụng riêng biệt trên hệ thống của khách hàng, là bắt đầu một quy trình bên ngoài (cũng có thể không thành công trong các tình huống quan trọng!) Và để điều đó tạo ra sự sụp đổ từ quy trình hiện tại của bạn (xem Superassert.NET from John Robbins). Bạn thậm chí có thể đi xa như vậy, để đưa nhị phân bên ngoài vào tài nguyên ứng dụng của bạn, trích xuất nó từ đó khi khởi động (để giảm thiểu thất bại trong các situtations quan trọng) vào đĩa (nếu bạn dám).

+0

Trong khi có sự khôn ngoan đang được cẩn thận với hành động của bạn trong một vụ tai nạn ứng dụng, nó cũng tốt để suy nghĩ về những gì ứng dụng của bạn là hoàn thành. Nếu bạn đang trong quá trình sản xuất, hãy cẩn thận - Tuy nhiên, nếu bạn đang viết một ứng dụng xử lý hàng loạt, bạn gần như chắc chắn sẽ tạo ra minidump cho các mục đích gỡ lỗi sau thay vì phải thực hiện repro tốn thời gian. Lời khuyên chung: luôn xem xét tình hình của bạn trước khi đưa ra quyết định thiết kế và cảnh giác với lời khuyên quá rộng. – jhclark

+0

@jhclark Tôi hoàn toàn _not_ chống lại viết một bãi rác nhỏ/sụp đổ; trong thực tế, một bãi chứa _proper_ là công cụ phân tích bài đăng tốt nhất mà người ta có thể yêu cầu. Nhưng điểm không phải là cố gắng viết nó từ _within_ quá trình nạn nhân. Như vậy thường không đáng tin cậy. Có một số loại quá trình giám sát bên ngoài là con đường để đi (thậm chí một cái gì đó giống như Sysinternals procdump có thể làm cho các tình huống trong nhà). IMHO là đúng bất kể loại ứng dụng hoặc những gì đang cố gắng thực hiện. –

0

Tùy thuộc vào loại thông tin bạn cần, bạn có thể thêm trình xử lý cho sự kiện AppDomain.UnhandledException? (Tôi biết nó không chính xác những gì bạn đang tìm kiếm, nhưng nó chắc chắn có sẵn trên các máy khách.)

0

Bạn có sử dụng khung đăng nhập như log4net không? Thông thường, bạn tắt thông báo mức gỡ lỗi cho bản phát hành. Tuy nhiên, bạn có thể nghĩ đến việc viết một ứng dụng đặc biệt chỉ ghi vào một tệp trong một số trường hợp nhất định (như một sự cố). Appender này viết lúc đầu vào một bộ nhớ đệm chỉ có bộ nhớ mà có thể được ghi vào một tập tin, sau đó - kích hoạt ví dụ bởi một ngoại trừ như đề nghị của 280Z28.

+0

Một bãi chứa nhỏ là ** cách ** hữu ích hơn, so với tệp nhật ký. Nó nắm bắt trạng thái hoàn chỉnh của một ứng dụng, vào thời điểm đó, một ngoại lệ không bị bắt được ném ra. Bạn có thể tải nó lên trong trình gỡ rối và nhận thông tin biểu tượng đầy đủ, liên kết thuận tiện với mã nguồn, dấu vết ngăn xếp đầy đủ của tất cả các chuỗi, vị trí lỗi chính xác, thông tin về các mô-đun đã nạp, bộ nhớ và bất kỳ số thông tin tùy chỉnh nào bạn muốn thêm . – IInspectable

5

Bạn có thể P/Gọi hàm MiniDumpWriteDump của sự kiện AppDomain.UnhandledException.

Trong trường hợp này, bạn có thể kết xuất nhật ký của dữ liệu ngoại lệ .NET và ghi một tệp nhỏ vào tệp.

Ngoài ra còn có một thread on the MSDN forums mô tả chữ ký P/Gọi và sử dụng hợp lý.

+1

Không, [bạn không thể làm điều này một cách an toàn] (http://stackoverflow.com/questions/1134048/generating-net-crash-dumps-automatically/1135666#comment57477239_1237097). 'MiniDumpWriteDump' ** phải ** được gọi từ một tiến trình riêng biệt. – IInspectable

6

Tôi nghĩ nếu ứng dụng của bạn được hosed thì bạn cũng có thể chụp ảnh khi tạo tệp kết xuất nhỏ, điều tồi tệ nhất sẽ xảy ra là gì, ứng dụng của bạn sẽ gặp sự cố? Nó đang làm điều đó anyway, vì vậy bạn cũng có thể thử.
Mã trong số MSDN forum mentioned by VoiDed có vẻ khá chắc chắn. Tôi cần một người phiên bản VB.Net vì vậy đây là một phiên bản VB cho bất cứ ai mà có thể cần nó:

Friend Class MiniDump 
    'Code converted from C# code found here: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/6c8d3529-a493-49b9-93d7-07a3a2d715dc 

    Private Enum MINIDUMP_TYPE 
     MiniDumpNormal = 0 
     MiniDumpWithDataSegs = 1 
     MiniDumpWithFullMemory = 2 
     MiniDumpWithHandleData = 4 
     MiniDumpFilterMemory = 8 
     MiniDumpScanMemory = 10 
     MiniDumpWithUnloadedModules = 20 
     MiniDumpWithIndirectlyReferencedMemory = 40 
     MiniDumpFilterModulePaths = 80 
     MiniDumpWithProcessThreadData = 100 
     MiniDumpWithPrivateReadWriteMemory = 200 
     MiniDumpWithoutOptionalData = 400 
     MiniDumpWithFullMemoryInfo = 800 
     MiniDumpWithThreadInfo = 1000 
     MiniDumpWithCodeSegs = 2000 
    End Enum 

    <Runtime.InteropServices.DllImport("dbghelp.dll")> _ 
    Private Shared Function MiniDumpWriteDump(_ 
     ByVal hProcess As IntPtr, _ 
     ByVal ProcessId As Int32, _ 
     ByVal hFile As IntPtr, _ 
     ByVal DumpType As MINIDUMP_TYPE, _ 
     ByVal ExceptionParam As IntPtr, _ 
     ByVal UserStreamParam As IntPtr, _ 
     ByVal CallackParam As IntPtr) As Boolean 
    End Function 

    Friend Shared Sub MiniDumpToFile(ByVal fileToDump As String) 
     Dim fsToDump As IO.FileStream = Nothing 

     If (IO.File.Exists(fileToDump)) Then 
      fsToDump = IO.File.Open(fileToDump, IO.FileMode.Append) 
     Else 
      fsToDump = IO.File.Create(fileToDump) 
     End If 

     Dim thisProcess As Process = Process.GetCurrentProcess() 
     MiniDumpWriteDump(thisProcess.Handle, _ 
          thisProcess.Id, _ 
          fsToDump.SafeFileHandle.DangerousGetHandle(), _ 
          MINIDUMP_TYPE.MiniDumpNormal, _ 
          IntPtr.Zero, _ 
          IntPtr.Zero, _ 
          IntPtr.Zero) 
     fsToDump.Close() 
    End Sub 
End Class 

Chỉ cần chắc chắn rằng bạn kiên cố eception xử lý các cuộc gọi đến nó và bạn sẽ có tương đối an toàn.

+2

* "Điều tồi tệ nhất sẽ xảy ra, ứng dụng của bạn sẽ sụp đổ là gì?" * - Đó không phải là điều tồi tệ nhất có thể xảy ra. Một kịch bản tồi tệ hơn sẽ là việc gọi 'MiniDumpWriteDump' sẽ khóa lại quá trình của bạn và ngăn chặn nó chấm dứt. Một trong những điều đầu tiên mà 'MiniDumpWriteDump' thực hiện là tạm dừng tất cả các luồng trong tiến trình. Nếu bạn không may mắn, một trong những chủ đề đó nằm ở giữa phân bổ bộ nhớ heap. Và khi 'MiniDumpWriteDump' cố gắng cấp phát bộ nhớ heap, nó sẽ vô thời hạn chờ khóa được giải phóng, nhưng nó được giữ bởi một chuỗi bị treo. Bạn không thể thực hiện điều này một cách an toàn. – IInspectable

+0

Bạn có thể giết quá trình trong trạng thái này không? Nếu điều này làm việc trong 99% các sự cố và deadlocks trong 1%, nơi tất cả người dùng phải làm là giết chết tôi nghĩ rằng đó là một thương mại công bằng, hoàn cảnh phụ thuộc. Sẽ bắt đầu một quy trình mới từ công việc xử lý bị lỗi? – jcmcbeth

9

Bạn có thể cấu hình Windows Error Reporting (WER) để tạo ra một đổ sụp đổ trong một thư mục cụ thể bằng cách sử dụng kịch bản registry sau đây:

 
Windows Registry Editor Version 5.00 
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps] 
"DumpFolder"="C:\\Dumps" 
"DumpCount"=dword:00000064 
"DumpType"=dword:00000002 
"CustomDumpFlags"=dword:00000000 

Các bãi sẽ đi vào C: \ Dumps với một tên phản ánh tên của quá trình bị lỗi. DumpType = 2 cung cấp kết xuất bộ nhớ đầy đủ. DumpType = 1 cho một bãi chứa nhỏ. Trên máy 64 bit, bạn không cần phải đặt chúng dưới các nút Wow32.WER chỉ sử dụng khoá đăng ký không phải WOW được chỉ định ở trên.

Tùy thuộc vào loại sự cố, phương pháp này có thể không hoạt động. Tôi vẫn chưa tìm ra lý do tại sao hoặc loại tai nạn nào mà nó không bị bắt. Bất kỳ ai?

+2

Như đã đề cập ở đây (http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx) Tôi không làm việc này cho mã được quản lý. – uli78

+0

"Các ứng dụng tạo báo cáo sự cố tùy chỉnh của riêng chúng, bao gồm các ứng dụng .NET, không được tính năng này hỗ trợ" –

+3

Tôi đã thử điều này và nó ** hoạt động cho mã được quản lý ** - trong trường hợp thử nghiệm của tôi là khung 4.5 . Nhưng tôi đã phải sử dụng tuyên bố sau trong ứng dụng .net của tôi: Application.SetUnhandledExceptionMode (UnhandledExceptionMode.ThrowException); –

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