ADPlus または DebugDiag を使用してクラッシュ ダンプ ファイルを生成する方法は知っていますが、これらのツールをインストールせずに顧客のコンピューターでこれを行う方法があるかどうか疑問に思っています...具体的には、アプリケーションを構成できるようにしたいと考えています (たとえば、レジストリ値を使用して) 重大な障害が発生した場合にクラッシュ ダンプを生成します。より具体的には、C# アプリケーションからこれを実行できるようにする必要がありますが、必要に応じて P/Invoke を実行してもかまいません。ありがとう!
7 に答える
次のレジストリスクリプトを使用して、特定のディレクトリにクラッシュダンプを作成するようにWindowsエラー報告(WER)を構成できます。
Windowsレジストリエディタバージョン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:\Dumpsに移動します。DumpType = 2は、フルメモリダンプを提供します。DumpType=1はミニダンプを提供します。64ビットマシンでは、これらをWow32ノードの下に置く必要はありません。WERは、上記で指定された非WOWレジストリキーのみを使用します。
クラッシュの種類によっては、この方法が機能しない場合があります。なぜ、またはどのクラッシュタイプがキャッチされないのかはまだわかりません。誰?
「失敗した」プロセス (またはスレッド) 自体からミニダンプを作成することは簡単ではないか、正確ではない可能性があることに注意してください ( MiniDumpWriteDump関数の備考も参照)。
その上、プロセスがクラッシュ ダンプを作成する必要があるほど怒っている場合、通常、全体の状況は非常に混乱しているため、クラッシュ ダンプを作成しようとしても別のクラッシュが発生する可能性があります (ハングアップのような状況 - しかし、それらは現在のプロセス内から「キャッチ」するのが難しい)。
クライアントのシステムに個別のアプリケーションをインストールできない場合にできる「最善の」方法は、外部プロセスを開始し (重大な状況では失敗する可能性もあります!)、現在のプロセスからクラッシュダンプを作成することです ( Superassert. NET から John Robbins )。外部バイナリをアプリのリソースに配置し、起動時に (重大な状況での障害を最小限に抑えるために) そこからディスクに (勇気がある場合) 抽出することもできます。
アプリがホースされている場合は、ミニ ダンプ ファイルの作成を試してみるとよいと思います。最悪の場合、アプリがクラッシュしますか? とにかくそれをやっているので、試してみてください。VoiDed が言及し
た MSDN フォーラムのコードは、かなりしっかりしているようです。VB.Net バージョンが必要だったので、必要な方のために VB バージョンを以下に示します。
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
それへの呼び出しを確実に処理することを確認してください。そうすれば、比較的安全になるはずです。
イベントでP/Invokedbghelp.dll
のMiniDumpWriteDump
関数を呼び出すことができAppDomain.UnhandledException
ます。
この場合、.NET 例外データのログをダンプし、ミニダンプをファイルに書き込むことができます。
MSDN フォーラムには、P/Invoke 署名と適切な使用法について説明しているスレッドもあります。
AppDomain.UnhandledException
必要な情報の種類に応じて、イベントのハンドラーを追加できますか? (あなたが探しているものではないことはわかっていますが、クライアント マシンで利用できることは間違いありません。)
log4net のようなロギング フレームワークを使用していますか? 通常、リリースのデバッグ レベル メッセージをオフにします。ただし、特定の場合 (クラッシュなど) にのみファイルにログを記録する特別なアペンダーを作成することを考えることができます。このアペンダーは、最初にファイルに書き込むことができるメモリのみのリングバッファーに書き込みます。後で、280Z28 で提案されているような例外ハンドラーによってトリガーされます。