3

我一直在尝试创建一个函数,该函数将为给定的进程 ID 编写一个小型转储文件。到目前为止,我有这个:

import win32con, win32api, win32file, ctypes
dbghelp = ctypes.windll.dbghelp 

def createMiniDump(pid, file_name):
    # Adjust privileges.
    adjustPrivilege(win32security.SE_DEBUG_NAME)
    pHandle = win32api.OpenProcess(
                win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ ,
                0, pid)
    print 'pHandle Status: ', win32api.FormatMessage(win32api.GetLastError())
    fHandle = win32file.CreateFile(file_name,
                               win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                               win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
                               None,
                               win32file.CREATE_ALWAYS,
                               win32file.FILE_ATTRIBUTE_NORMAL,
                               None)

    print 'fHandle Status: ', win32api.FormatMessage(win32api.GetLastError())
    success = dbghelp.MiniDumpWriteDump(pHandle.handle,   # Process handle
                                     pid,                 # Process ID
                                     fHandle.handle,      # File handle
                                     0,         # Dump type - MiniDumpNormal
                                     None,      # Exception parameter
                                     None,      # User stream parameter
                                     None,      # Callback parameter
                                     )
    print 'MiniDump Status: ', win32api.FormatMessage(win32api.GetLastError())
    return success

进程和文件句柄创建成功。但是,对 MiniDumpWriteDump 的调用会设置以下错误: Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

有没有人知道为什么会这样?

4

2 回答 2

3

我遇到的唯一问题是跨架构转储,即当您的本地进程是 64 位进程时转储 32 位进程,反之亦然。如果您环顾网络,您会发现很多参考标准建议是从 32 位进程中获取 32 位转储,从 64 中获取 64。请参阅不要使用 64 位任务管理器收集 32 位进程的转储捕获x64 机器上 32 位进程的内存转储 我不知道为什么,但我想这样做。(尽管从技术上讲,在 x64 窗口上它们都是64 位进程,但 32 位进程只是自欺欺人……带有额外的线程堆栈以及 TEB 和 PEB。

异常指针和当前线程 ID 仅在您从进程内转储时才相关。如果您完整阅读 MSDN 条目,它建议创建一个辅助线程并将其从转储中排除以有意义地获取当前线程堆栈,这显然仅在您转储当前进程时才有意义。此外,有时在诊断挂起进程时非常有用的转储外部进程不会有 PEXCEPTION_POINTER 信息。我也做了很多外部进程的小型转储,没有设置 PEXCEPTION_POINTER 或回调,但回调非常有用。

于 2012-01-12T12:45:22.387 回答
0

您缺少一个准备好的MINIDUMP_EXCEPTION_INFORMATION结构作为MiniDumpWriteDump(). 这是成功转储的必要条件。

将其ThreadId字段设置为GetCurrentThreadId()。将其ClientPointers字段设置为 FALSE。这里真正的诀窍是ExceptionPointers字段。我知道获得 a 的唯一方法PEXCEPTION_POINTERS是通过AddVectoredExceptionHandler(). 回调传递了一个PEXCEPTION_POINTERS参数。因此,您需要将所有转储代码移动到该回调中,以便PEXCEPTION_POINTERS在转储时访问 a。不幸的是,这也意味着您将受到触发转储的未处理异常的摆布(除非您可以找到另一种获取PEXCEPTION_POINTERS.

于 2012-01-06T17:49:12.790 回答