どうすれば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て両方を取得しますか?
使用例
MiniDumpWriteDumpDelphiの関数を使用してミニダンプを作成しようとしています。
この関数には、いくつかのオプションのパラメーターがあります。
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;
EExternalDelphiの例外がすべての「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でのフィルタリングされていないハンドラーの設定)