internal static Task CollectDumpAsync(Process process, string outputFile, NETCore.Client.DumpType type) { // We can't do this "asynchronously" so just Task.Run it. It shouldn't be "long-running" so this is fairly safe. return(Task.Run(() => { // Open the file for writing using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { var exceptionInfo = new NativeMethods.MINIDUMP_EXCEPTION_INFORMATION(); NativeMethods.MINIDUMP_TYPE dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal; switch (type) { case NETCore.Client.DumpType.Full: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; break; case NETCore.Client.DumpType.WithHeap: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithPrivateReadWriteMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; break; case NETCore.Client.DumpType.Normal: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo; break; } // Retry the write dump on ERROR_PARTIAL_COPY for (int i = 0; i < 5; i++) { // Dump the process! if (NativeMethods.MiniDumpWriteDump(process.Handle, (uint)process.Id, stream.SafeFileHandle, dumpType, ref exceptionInfo, IntPtr.Zero, IntPtr.Zero)) { break; } else { int err = Marshal.GetHRForLastWin32Error(); if (err != NativeMethods.ERROR_PARTIAL_COPY) { Marshal.ThrowExceptionForHR(err); } } } } })); }
/// <summary> /// Collects a mini dump (optionally with full memory) for the given process and writes it to the given file path /// </summary> public void CollectDump(Process process, string dumpFilePath, bool fIncludeFullHeap) { IntPtr hFile = IntPtr.Zero; try { hFile = NativeMethods.CreateFile( lpFileName: dumpFilePath, dwDesiredAccess: NativeMethods.EFileAccess.GenericWrite, dwShareMode: NativeMethods.EFileShare.None, lpSecurityAttributes: IntPtr.Zero, dwCreationDisposition: NativeMethods.ECreationDisposition.CreateAlways, dwFlagsAndAttributes: NativeMethods.EFileAttributes.Normal, hTemplateFile: IntPtr.Zero ); if (hFile == NativeMethods.INVALID_HANDLE_VALUE) { int hresult = Marshal.GetHRForLastWin32Error(); Exception hresultException = Marshal.GetExceptionForHR(hresult); throw hresultException; } // Ensure the dump file will contain all the info needed (full memory, handle, threads) NativeMethods.MINIDUMP_TYPE dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo; if (fIncludeFullHeap) { dumpType |= NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo; } NativeMethods.MINIDUMP_EXCEPTION_INFORMATION exceptionInfo = new NativeMethods.MINIDUMP_EXCEPTION_INFORMATION(); bool result = NativeMethods.MiniDumpWriteDump( hProcess: process.Handle, ProcessId: process.Id, hFile: hFile, DumpType: dumpType, ExceptionParam: ref exceptionInfo, UserStreamParam: IntPtr.Zero, CallbackParam: IntPtr.Zero ); if (result == false) { int hresult = Marshal.GetHRForLastWin32Error(); Exception hresultException = Marshal.GetExceptionForHR(hresult); throw hresultException; } } finally { NativeMethods.CloseHandle(hFile); } }
internal static void CollectDump(Process process, string outputFile, DumpTypeOption type) { // Open the file for writing using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { NativeMethods.MINIDUMP_EXCEPTION_INFORMATION exceptionInfo = default(NativeMethods.MINIDUMP_EXCEPTION_INFORMATION); NativeMethods.MINIDUMP_TYPE dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal; switch (type) { case DumpTypeOption.Full: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; break; case DumpTypeOption.WithHeap: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithPrivateReadWriteMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; break; case DumpTypeOption.Mini: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo; break; } // Retry the write dump on ERROR_PARTIAL_COPY for (int i = 0; i < 5; i++) { // Dump the process! if (NativeMethods.MiniDumpWriteDump(process.Handle, (uint)process.Id, stream.SafeFileHandle, dumpType, ref exceptionInfo, IntPtr.Zero, IntPtr.Zero)) { break; } else { int err = Marshal.GetHRForLastWin32Error(); if (err != NativeMethods.ERROR_PARTIAL_COPY) { Marshal.ThrowExceptionForHR(err); } } } } }
internal static void CollectDump(int processId, string outputFile, DumpTypeOption type) { // The managed Process (via Process.GetProcessById) type can not be used to get the handle for a process that is in the middle of exiting such // that it has set an exit code, but not actually exited. This is because for compat reasons the Process class will throw in these circumstances. using SafeProcessHandle processHandle = NativeMethods.OpenProcess(NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_VM_READ, false, processId); if (processHandle.IsInvalid) { throw new ArgumentException($"Invalid process id {processId} error: {Marshal.GetLastWin32Error()}"); } // Open the file for writing using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { NativeMethods.MINIDUMP_TYPE dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal; switch (type) { case DumpTypeOption.Full: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; break; case DumpTypeOption.Heap: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithPrivateReadWriteMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo | NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation; break; case DumpTypeOption.Mini: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal | NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo; break; case DumpTypeOption.Triage: dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpFilterTriage | NativeMethods.MINIDUMP_TYPE.MiniDumpIgnoreInaccessibleMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithoutOptionalData | NativeMethods.MINIDUMP_TYPE.MiniDumpWithProcessThreadData | NativeMethods.MINIDUMP_TYPE.MiniDumpFilterModulePaths | NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules | NativeMethods.MINIDUMP_TYPE.MiniDumpFilterMemory | NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData; break; } // Retry the write dump on ERROR_PARTIAL_COPY for (int i = 0; i < 5; i++) { // Dump the process! if (NativeMethods.MiniDumpWriteDump(processHandle.DangerousGetHandle(), (uint)processId, stream.SafeFileHandle, dumpType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) { break; } else { int err = Marshal.GetHRForLastWin32Error(); if (err != NativeMethods.ERROR_PARTIAL_COPY) { Marshal.ThrowExceptionForHR(err); } } } } }