2009-07-15 12 views
35

私はADPlusまたはDebugDiagでクラッシュダンプファイルを生成する方法を知っていますが、これらのツールをインストールせずに顧客のコンピュータでこれを行う方法があるのだろうかと思います。クリティカルな障害が発生した場合にクラッシュダンプを生成するために、(レジストリ値などを使用して)自分のアプリケーションを構成できるようにします。より具体的には、私はC#アプリケーションからこれを行うことができる必要がありますが、私はP/Invoke'ing必要な場合は気にしません。ありがとう!.NETクラッシュダンプを自動的に生成する

答えて

14

"失敗"プロセス(またはスレッド)自体からミニダンプを作成することは簡単ではないか、正確ではない可能性があります(MiniDumpWriteDump関数の解説)。

さらに、プロセスがクラッシュダンプを書く必要があるような怒りに陥っている場合、クラッシュダンプの作成を試みても別のクラッシュが発生する可能性があります。現在のプロセスから「キャッチ」するのがさらに難しいかもしれません)。

クライアントのシステムに別個のアプリケーションをインストールできない場合は、外部プロセスを開始することが重要です(これは重大な状況でも失敗する可能性があります)、現在のプロセスからクラッシュダンプを作成させることです(Superassert.NET from John Robbins参照)。あなたはアプリのリソースに外部バイナリを置くように、これまでに行っても、起動時に(批判的な状況での失敗を最小限に抑えるために)そこからそれを取り出してディスクに変換することができます。

+0

アプリケーションのクラッシュ中にあなたの行動に注意を払っている間に、あなたのアプリケーションが達成していることについて考えることも良いことです。実稼働中の場合は、細心の注意を払ってください。しかし、バッチ処理アプリケーションを作成する場合は、後でデバッグするためにミニダンプを作成する方が時間がかかります。一般的なアドバイス:設計上の決定を下す前に、常にあなたの状況を考慮し、過度に広範なアドバイスに注意してください。 – jhclark

+0

@jhclark私はミニ/クラッシュダンプを書いているのに全く反対していません。実際、_proper_ダンプは、頼むことができる最良の死後解析ツールです。しかし、そのポイントは、犠牲者プロセスの中からそれを書くことを試みることではありません。それは一般的に信頼できないものです。何らかの外部ウォッチドッグプロセスを持つことは、(たとえSysinternalsのprocdumpが社内の状況のた​​めにできるようなものであっても)行く方法です。 IMHOは、アプリケーションの種類や達成しようとしていることに関係なく真です。 –

0

必要な情報の種類に応じて、AppDomain.UnhandledExceptionイベントのハンドラを追加できますか? (あなたが探しているものではないことは分かっていますが、クライアントマシンでは利用可能です。)

0

log4netのようなロギングフレームワークを使用していますか?通常は、リリースのデバッグレベルのメッセージをオフにします。しかし、特定のケース(クラッシュのような)でのみファイルに記録する特別なアペンダーを書くことについて考えることができます。このアペンダは、最初にファイルに書き込むことができるメモリ専用のリングバッファに書き込みます。後で、例えば280Z28のような例外ハンドラによってトリガされます。

+0

ミニ・ダンプは、ログ・ファイルよりも**便利です**。アプリケーションの完全な状態を取得します。その時点で、キャッチされない例外がスローされます。デバッガでロードして、ソースコード、すべてのスレッドの完全なスタックトレース、正確な障害位置、ロードされたモジュールに関する情報、メモリ、および追加したいと思う任意の数のカスタム情報。 – IInspectable

5

AppDomain.UnhandledExceptionイベントでは、dbghelp.dllMiniDumpWriteDump機能をP/Invokeできました。

この場合、.NET例外データのログをダンプし、ミニダンプをファイルに書き込むことができます。

また、P/Invokeの署名と適切な使い方を説明するthread on the MSDN forumsもあります。

+1

いいえ、[これは安全に行うことはできません](http://stackoverflow.com/questions/1134048/generating-net-crash-dumps-automatically/1135666#comment57477239_1237097)。 'MiniDumpWriteDump' **は、別のプロセスから呼び出さなければなりません**。 – IInspectable

6

あなたのアプリがフックされている場合は、ミニダンプファイルを作成する際にもショットを取ることができますが、最悪のことは起こるでしょう、あなたのアプリはクラッシュしますか?それはとにかくやっているので、試してみてください。
MSDN forum mentioned by VoiDedのコードはかなり安定しているようです。私はここでそれを必要とするかもしれない人のためのVBのバージョンがありますVB.Netバージョンを必要:

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 

ちょうどあなたがしっかりとそれへの呼び出しを扱うeception、あなたは比較的安全である必要があります。

+2

*「最悪のことは起こるだろう、あなたのアプリはクラッシュするだろうか?」* - それは起こり得る最悪ではない。さらに悪いシナリオは、 'MiniDumpWriteDump'を呼び出すとプロセスがデッドロックされ、プロセスが終了しないようにすることです。 'MiniDumpWriteDump'が行う最初のことの1つは、プロセス内のすべてのスレッドを中断することです。あなたが不運な場合は、それらのスレッドの1つがヒープメモリの割り当ての途中です。そして、 'MiniDumpWriteDump'がヒープメモリを割り当てようとすると、ロックが解放されるのを無期限に待ちますが、中断されたスレッドによって保持されます。これを安全に行うことはできません。 – IInspectable

+0

この状態でプロセスを強制終了できますか?これがクラッシュとデッドロックの99%で動作し、1%ですべてのユーザーが強制終了する必要がある場合、私はそれが公正な取引であると考えています。クラッシュしたプロセスの作業から新しいプロセスを開始するか? – jcmcbeth

9

次のレジストリスクリプトを使用して、特定のディレクトリにクラッシュダンプを作成する(WER)をWindowsエラー報告を構成することができます。

 
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になります:\は反映名前でダンプしますクラッシュしたプロセスの名前。 DumpType = 2は完全なメモリダンプを与えます。 DumpType = 1はミニダンプを与えます。 64ビットマシンでは、これらをWow32ノードの下に置く必要はありません。WERは上記のWOW以外のレジストリキーのみを使用します。

クラッシュの種類によっては、この方法が機能しないことがあります。私はまだ、なぜ、どのクラッシュタイプが捕まえられないのか把握していない。誰でも?

+2

ここに記載されているように(http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx)私はこれがマネージコードのために機能するわけではありません。 – uli78

+0

".NETアプリケーションを含む独自のカスタムクラッシュレポートを行うアプリケーションはこの機能ではサポートされていません" –

+3

これを試してみましたが、**管理されたコードで動作します** - 私のテストケースではフレームワーク4.5 。しかし、私は、次の文を使用しなければならなかった.net App:Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); –