我一直在尝试创建一个函数,该函数将为给定的进程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.
有人知道为什么会这样吗?在
缺少一个准备好的
MINIDUMP_EXCEPTION_INFORMATION
结构作为MiniDumpWriteDump()
的第五个参数。这是一个成功的倾倒的必要条件。在将其
ThreadId
字段设置为GetCurrentThreadId()
。将其ClientPointers
字段设置为FALSE。这里真正的诀窍是ExceptionPointers
字段。我所知道的获得PEXCEPTION_POINTERS
的唯一方法是通过AddVectoredExceptionHandler()
分配一个回调。回调通过一个PEXCEPTION_POINTERS
参数。因此,您需要将所有转储代码移到该回调中,以便在转储时访问PEXCEPTION_POINTERS
。不幸的是,这也意味着您将受到触发转储的未处理异常的摆布(除非您可以找到另一种方法来获得PEXCEPTION_POINTERS
)。在我遇到的唯一问题是跨体系结构转储,即当本地进程是64位进程时转储32位进程,反之亦然。如果你环顾网络,你会发现大量的参考标准建议是从32位进程中获取32位转储,从64位进程获取64位转储。参见Do not collect 32bit process' dumps with 64 bit task manager 和{a2} 我不知道为什么,但我愿意。(即使从技术上讲,在x64 windows上,它们都是64位进程,而32位进程只是在自欺欺人。。有一个额外的线程堆栈和TEB和PEB。在
异常指针和当前线程id只有在从进程内转储时才相关。 如果您完全读取MSDN条目,它建议您创建一个helper线程,并将其从转储中排除,以获得有意义的当前线程堆栈,这显然只有在您正在转储当前进程时才有意义。 另外,转储一个外部进程(有时在诊断挂起进程时非常有用)不会有peexception_指针信息。我还做了大量的外部进程的小转储,没有设置peexception_指针,也没有回调,但是回调非常有用。在
相关问题 更多 >
编程相关推荐