どうすればEXCEPTION_POINTERS
、つまり両方を取得できますか?
PEXCEPTION_RECORD
とPCONTEXT
EExternal
例外中のデータ?
バックグラウンド
Windowsが例外をスローすると、PEXCEPTION_POINTERS
;が渡されます。例外情報へのポインタ:
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
DelphiEExternal
が例外をスローすると、その情報の半分しか含まれていませんPEXCEPTION_RECORD
。
EExternal = class(Exception)
public
ExceptionRecord: PExceptionRecord;
end;
例外の間に、どのようにしEExternal
て両方を取得しますか?
使用例
MiniDumpWriteDump
Delphiの関数を使用してミニダンプを作成しようとしています。
この関数には、いくつかのオプションのパラメーターがあります。
function MiniDumpWriteDump(
hProcess: THandle; //A handle to the process for which the information is to be generated.
ProcessID: DWORD; //The identifier of the process for which the information is to be generated.
hFile: THandle; //A handle to the file in which the information is to be written.
DumpType: MINIDUMP_TYPE; //The type of information to be generated.
{in, optional}ExceptionParam: PMinidumpExceptionInformation; //A pointer to a MINIDUMP_EXCEPTION_INFORMATION structure describing the client exception that caused the minidump to be generated.
{in, optional}UserStreamParam: PMinidumpUserStreamInformation;
{in, optional}CallbackParam: PMinidumpCallbackInformation): Boolean;
基本的なレベルでは、3つのオプションのパラメーターを省略できます。
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFileHandle,
nil, //PMinidumpExceptionInformation
nil,
nil);
そしてそれは成功します。欠点は、ミニダンプに例外情報がないことです。その情報は(オプションで)4番目のminiExceptionInfoパラメーターを使用して渡されます。
TMinidumpExceptionInformation = record
ThreadId: DWORD;
ExceptionPointers: PExceptionPointers;
ClientPointers: BOOL;
end;
PMinidumpExceptionInformation = ^TMinidumpExceptionInformation;
これは良いEXCEPTION_POINTERS
ことですが、例外が発生したときにWindowsによって提供されるを取得する方法が必要です。
TExceptionPointers
構造には2つのメンバーが含まれます。
EXCEPTION_POINTERS = record
ExceptionRecord : PExceptionRecord;
ContextRecord : PContext;
end;
EExternal
Delphiの例外がすべての「Windows」例外のベースであり、必要なものが含まれていることを私は知っていますPExceptionRecord
。
EExternal = class(Exception)
public
ExceptionRecord: PExceptionRecord;
end;
ただし、関連付けられたは含まれていませんContextRecord
。
PEXCEPTION_RECORD
十分ではありませんか?
に渡そうとするEXCEPTION_POINTERS
と、 nilMiniDumpWriteDump
のままになります。ContextRecord
procedure TDataModule1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
ei: TExceptionPointers;
begin
if (E is EExternal) then
begin
ei.ExceptionRecord := EExternal(E).ExceptionRecord;
ei.ContextRecord := nil;
GenerateDump(@ei);
end;
...
end;
function GenerateDump(exceptionInfo: PExceptionPointers): Boolean;
var
miniEI: TMinidumpExceptionInformation;
begin
...
miniEI.ThreadID := GetCurrentThreadID();
miniEI.ExceptionPointers := exceptionInfo;
miniEI.ClientPointers := True;
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFileHandle,
@miniEI, //PMinidumpExceptionInformation
nil,
nil);
end;
その後、関数はエラーで失敗します0x8007021B
ReadProcessMemoryまたはWriteProcessMemoryリクエストの一部のみが完了しました
どうSetUnhandledExceptionFilter
ですか?
SetUnhandledExceptionFilter
必要なポインタを使って取得してみませんか?
SetUnhandledExceptionFilter(@DebugHelpExceptionFilter);
function DebugHelpExceptionFilter(const ExceptionInfo: TExceptionPointers): Longint; stdcall;
begin
GenerateDump(@ExceptionInfo);
Result := 1; //1 = EXCEPTION_EXECUTE_HANDLER
end;
それに関する問題は、例外がフィルタリングされていない場合にのみ、フィルタリングされていない例外ハンドラが起動することです。これはDelphiであり、例外を処理するためです。
procedure DataModule1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
ei: TExceptionPointers;
begin
if (E is EExternal) then
begin
//If it's EXCEPTION_IN_PAGE_ERROR then we have to terminate *now*
if EExternal(E).ExceptionRecord.ExceptionCode = EXCEPTION_IN_PAGE_ERROR then
begin
ExitProcess(1);
Exit;
end;
//Write minidump
...
end;
{$IFDEF SaveExceptionsToDatabase}
SaveExceptionToDatabase(Sender, E);
{$ENDIF}
{$IFDEF ShowExceptionForm}
ShowExceptionForm(Sender, E);
{$ENDIF}
end;
アプリケーションは、WER障害で終了することはなく、また終了することも望んでいません。
EXCEPTION_POINTERS
中に取得するにはどうすればよいEExternal
ですか?
注:バックグラウンド以降はすべて無視できます。それは私をよりスマートに見せるために不必要に設計されたフィラーです。
先制的な卑劣なHeffernanのコメント:Delphi5の使用をやめるべきです。
ボーナスリーディング
- MSDN:クラッシュダンプ分析(Windows)
(呼び出し方法の詳細な例
MiniDumpWriteDump
) - CodeProject:ミニダンプとVisual Studio .NETを使用したアプリケーションの事後デバッグ (概念、長所、およびミニダンプの生成と使用方法に関する一般的な説明)
- Stackoverflow:クラッシュしたときにプロセスのミニダンプを作成するにはどうすればよいですか? (ミニダンプの世界への最初の紹介)
- Stackoverflow:単一のアプリのMicrosoftエラーレポートを防ぐことはできますか? (Delphiでのフィルタリングされていないハンドラーの設定)