使用回调调用 MiniDumpWriteDump
我想使用 MiniDumpWriteDump 函数创建一些自定义转储文件(主要是,我想导出一个包含线程调用堆栈最少信息的转储文件),但我在定义需要传递的结构时遇到困难回调函数的参数
[StructLayout(LayoutKind.Explicit)]
internal struct MINIDUMP_CALLBACK_OUTPUT
{
[FieldOffset(0)]
public ulong ModuleWriteFlags;
[FieldOffset(0)]
public ulong ThreadWriteFlags;
}
public struct MINIDUMP_CALLBACK_INFORMATION
{
public IntPtr CallbackRoutine;
public IntPtr CallbackParam;
}
public delegate bool MINIDUMP_CALLBACK_ROUTINE(
IntPtr CallBackParam,
MINIDUMP_CALLBACK_INPUT input,
MINIDUMP_CALLBACK_OUTPUT output);
[DllImport("dbghelp.dll")]
public static extern bool MiniDumpWriteDump(IntPtr hProcess, Int32 ProcessId, IntPtr hFile, int DumpType,
IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallStackParam);
调用如下所示:
MINIDUMP_CALLBACK_INFORMATION mci;
MINIDUMP_CALLBACK_ROUTINE r = new MINIDUMP_CALLBACK_ROUTINE(MyCallback);
GC.KeepAlive(r);
mci.CallbackRoutine = Marshal.GetFunctionPointerForDelegate(r);
mci.CallbackParam = IntPtr.Zero;
IntPtr structPointer = Marshal.AllocHGlobal(Marshal.SizeOf(mci));
Marshal.StructureToPtr(mci, structPointer, true);
MiniDumpWriteDump(process[0].Handle, process[0].Id,
fs.SafeFileHandle.DangerousGetHandle(),
(int)MINIDUMP_TYPE.MiniDumpNormal,
Marshal.GetExceptionPointers(),
IntPtr.Zero,
structPointer);
Marshal.FreeHGlobal(structPointer);
所以我的问题是如何定义 MINIDUMP_CALLBACK_INPUT:
C 中引起问题的结构的定义是:
typedef struct _MINIDUMP_CALLBACK_INPUT
{
ULONG ProcessId;
HANDLE ProcessHandle;
ULONG CallbackType;
union
{
MINIDUMP_THREAD_CALLBACK Thread;
MINIDUMP_THREAD_EX_CALLBACK ThreadEx;
MINIDUMP_MODULE_CALLBACK Module;
MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;
MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;
} u;
} MINIDUMP_CALLBACK_INPUT
typedef struct _MINIDUMP_MODULE_CALLBACK
{
PWCHAR FullPath;
ULONGLONG BaseOfImage;
ULONG SizeOfImage;
ULONG CheckSum;
ULONG TimeDateStamp;
VS_FIXEDFILEINFO VersionInfo;
PVOID CvRecord;
ULONG SizeOfCvRecord;
PVOID MiscRecord;
ULONG SizeOfMiscRecord;
} MINIDUMP_MODULE_CALLBACK
I want to use the MiniDumpWriteDump function to create some custom dump files (mainly, i want to export a dump file that contains the minimum amount of information for the thread callstacks), but i am having difficulties defining the structures that need to be passed as a parameter to the callback function
[StructLayout(LayoutKind.Explicit)]
internal struct MINIDUMP_CALLBACK_OUTPUT
{
[FieldOffset(0)]
public ulong ModuleWriteFlags;
[FieldOffset(0)]
public ulong ThreadWriteFlags;
}
public struct MINIDUMP_CALLBACK_INFORMATION
{
public IntPtr CallbackRoutine;
public IntPtr CallbackParam;
}
public delegate bool MINIDUMP_CALLBACK_ROUTINE(
IntPtr CallBackParam,
MINIDUMP_CALLBACK_INPUT input,
MINIDUMP_CALLBACK_OUTPUT output);
[DllImport("dbghelp.dll")]
public static extern bool MiniDumpWriteDump(IntPtr hProcess, Int32 ProcessId, IntPtr hFile, int DumpType,
IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallStackParam);
And the call looks like this:
MINIDUMP_CALLBACK_INFORMATION mci;
MINIDUMP_CALLBACK_ROUTINE r = new MINIDUMP_CALLBACK_ROUTINE(MyCallback);
GC.KeepAlive(r);
mci.CallbackRoutine = Marshal.GetFunctionPointerForDelegate(r);
mci.CallbackParam = IntPtr.Zero;
IntPtr structPointer = Marshal.AllocHGlobal(Marshal.SizeOf(mci));
Marshal.StructureToPtr(mci, structPointer, true);
MiniDumpWriteDump(process[0].Handle, process[0].Id,
fs.SafeFileHandle.DangerousGetHandle(),
(int)MINIDUMP_TYPE.MiniDumpNormal,
Marshal.GetExceptionPointers(),
IntPtr.Zero,
structPointer);
Marshal.FreeHGlobal(structPointer);
So my question is how to define MINIDUMP_CALLBACK_INPUT:
The definition of the structures in C that pose problems are:
typedef struct _MINIDUMP_CALLBACK_INPUT
{
ULONG ProcessId;
HANDLE ProcessHandle;
ULONG CallbackType;
union
{
MINIDUMP_THREAD_CALLBACK Thread;
MINIDUMP_THREAD_EX_CALLBACK ThreadEx;
MINIDUMP_MODULE_CALLBACK Module;
MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;
MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;
} u;
} MINIDUMP_CALLBACK_INPUT
typedef struct _MINIDUMP_MODULE_CALLBACK
{
PWCHAR FullPath;
ULONGLONG BaseOfImage;
ULONG SizeOfImage;
ULONG CheckSum;
ULONG TimeDateStamp;
VS_FIXEDFILEINFO VersionInfo;
PVOID CvRecord;
ULONG SizeOfCvRecord;
PVOID MiscRecord;
ULONG SizeOfMiscRecord;
} MINIDUMP_MODULE_CALLBACK
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我想是工会给你添麻烦了吧?
如果 CallbackType==KernelMinidumpStatusCallback,则 CALLBACK_INPUT 结构定义为:
如果 CallbackType==ThreadCallback,则为:
如果 CallbackType==ThreadExCallback,则为:
依此类推(此来自 MSDN) - 看起来第 4 个成员可以是 8 种不同类型之一,取决于 CallbackType 等于什么。在内部,Windows 将为所有这些结构使用相同的内存块(将较小的结构填充到最大的结构)。在 C++ 中,通过类型转换很容易获得所需的类型。
我不知道如何在 C# 中执行此操作。我在C++中使用过MiniDumpWriteDump,但从未使用过回调函数。如果您可以确定 CallbackType 始终是一个值,您可以只编写一个结构的代码,但我不知道情况是否如此。
抱歉,我无法提供更多信息,但这也许有助于描述问题。
I take it that it is the union that is giving you trouble?
If CallbackType==KernelMinidumpStatusCallback, then the CALLBACK_INPUT structure is defined as:
If CallbackType==ThreadCallback, then it is:
If CallbackType==ThreadExCallback, then it is:
And so on (this is from MSDN) -- it looks like that 4th member can be one of 8 different types, depending on what CallbackType is equal to. Internally, Windows will use the same chunk of memory for all of these structures (padding the smaller ones to the largest one's size). In C++, it's an easy typecast to get the type you need.
I'm not sure how to do this in C#. I have used MiniDumpWriteDump in C++, but never used the callback function. If you could be sure that CallbackType was always one value, you could just code that one structure, but I don't know if this is the case.
Sorry I can't provide more information, but maybe this helps describe the problem.
这不是您问题的直接答案,而是一种解决方法...
您知道 ClrDump lib哪个可以满足您的需求?几年前我在一个项目中使用过它,它对我来说效果很好。
对作者评论的回答:
在网站上阅读:
我将 API 包装在以下类中:
然后,在初始化代码中的某个位置,我调用了 RegisterFilter 方法,该方法为当前进程中未处理的异常注册一个内部过滤器。如果进程因未处理的异常(可以是本机异常或托管异常)而崩溃,过滤器将捕获它并创建一个小型转储(具有指定的文件名)。以下是示例代码:
您可以阅读本文来了解不同的 MINIDUMP_TYPE选项,但我认为基本的(MiniDumpNormal)可以满足您的需求。
It's not a direct answer of your question but a workaround...
Do you know the ClrDump lib which does what you need ? I've used it for a project several years ago and it works fine for me.
Answer to author comment:
Read on the site:
I wrapped the API in the following class:
and then, somewhere in my initialization code, I called the method RegisterFilter which registers an internal filter for unhandled exceptions in the current process. If the process crashes with unhandled exception (it can be native or managed exception), the filter catches it and creates a minidump (with the specified file name). Here is a sample code for this:
You can read this article to understand the different MINIDUMP_TYPE options, but I think the basic one (MiniDumpNormal) could fit your needs.
使用这段代码定义一个32位联合结构:
我认为在64位平台上,无论ULONG是64,偏移量应该分别是{0,8,16,24}或{0,4,12,16}或 32 位。
编辑
我认为您可以使用 MarshalAsAttribute 来专门转换字段:
Use this code to define a structure with union in 32 bits:
I think that on a 64 bits platform, the offsets should be respectively { 0, 8, 16, 24 } or { 0, 4, 12, 16 } whether ULONG is 64 or 32 bits.
Edit
I think you can use the MarshalAsAttribute to specifically convert fields: