internal static Result DumpProcess(FileStream dumpFile, IntPtr processHandle, int pid) { IntPtr callbackParam = default; Result result = default; GCHandle callbackHandle = default; try { var callbackDelegate = new MiniDumpCallback(MiniDumpCallbackMethod); callbackHandle = GCHandle.Alloc(callbackDelegate); callbackParam = Marshal.AllocHGlobal(IntPtr.Size * 2); unsafe { var ptr = (MINIDUMP_CALLBACK_INFORMATION *)callbackParam; ptr->CallbackRoutine = Marshal.GetFunctionPointerForDelegate(callbackDelegate); ptr->CallbackParam = IntPtr.Zero; } #pragma warning disable S3869 // "SafeHandle.DangerousGetHandle" should not be called var fileHandle = dumpFile.SafeFileHandle.DangerousGetHandle(); #pragma warning restore S3869 // "SafeHandle.DangerousGetHandle" should not be called result.ReturnValue = MiniDumpWriteDump(processHandle, pid, fileHandle, GetMiniDumpType(), IntPtr.Zero, IntPtr.Zero, callbackParam); result.ErrorCode = Marshal.GetHRForLastWin32Error(); } catch (Exception e) { result.ErrorCode = Marshal.GetHRForLastWin32Error(); result.ReturnValue = 0; result.Exception = e; } finally { if (callbackParam != default) { Marshal.FreeHGlobal(callbackParam); } if (callbackHandle.IsAllocated) { callbackHandle.Free(); } } return(result); }
internal static Result DumpProcess(FileStream dumpFile, IntPtr processHandle, int pid) { IntPtr callbackParam = default(IntPtr); Result result = default(Result); try { var callbackDelegate = new MiniDumpCallback(MiniDumpCallbackMethod); callbackParam = Marshal.AllocHGlobal(IntPtr.Size * 2); unsafe { var ptr = (MINIDUMP_CALLBACK_INFORMATION *)callbackParam; ptr->CallbackRoutine = Marshal.GetFunctionPointerForDelegate(callbackDelegate); ptr->CallbackParam = IntPtr.Zero; } var fileHandle = dumpFile.SafeFileHandle.DangerousGetHandle(); GC.KeepAlive(callbackDelegate); result.ReturnValue = MiniDumpWriteDump(processHandle, pid, fileHandle, GetMiniDumpType(), IntPtr.Zero, IntPtr.Zero, callbackParam); result.ErrorCode = Marshal.GetHRForLastWin32Error(); } catch (Exception e) { result.ErrorCode = Marshal.GetHRForLastWin32Error(); result.ReturnValue = 0; result.Exception = e; } finally { if (callbackParam != default(IntPtr)) { Marshal.FreeHGlobal(callbackParam); } } return(result); }
public static int Main(string[] args) { if (args.Length != 2) { Console.WriteLine("Usage: CopyOnWriteDump <PID> <FileName.dmp>"); return(-1); } var pid = int.Parse(args[0]); var fileName = args[1]; HANDLE handle; try { var p = Process.GetProcessById(pid); handle = p.Handle; } catch (ArgumentException) { Console.WriteLine($"Process identified by {pid} does not exist"); return(-2); } var flags = PSS_CAPTURE_FLAGS.PSS_CAPTURE_VA_CLONE | PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLES | PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_NAME_INFORMATION | PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_BASIC_INFORMATION | PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION | PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_TRACE | PSS_CAPTURE_FLAGS.PSS_CAPTURE_THREADS | PSS_CAPTURE_FLAGS.PSS_CAPTURE_THREAD_CONTEXT | PSS_CAPTURE_FLAGS.PSS_CREATE_MEASURE_PERFORMANCE; HPSS snapshotHandle; Stopwatch sw = new Stopwatch(); sw.Start(); DWORD hr = PssCaptureSnapshot(handle, flags, IntPtr.Size == 8 ? 0x0010001F : 0x0001003F, out snapshotHandle); sw.Stop(); if (hr != 0) { Console.WriteLine($"PssCaptureSnapshot failed. ({hr})"); return(hr); } Console.WriteLine($"Snapshot Creation Time: {sw.ElapsedMilliseconds}ms"); sw.Reset(); sw.Start(); using (var fs = new FileStream(fileName, FileMode.Create)) { var callbackDelegate = new MiniDumpCallback(MiniDumpCallbackMethod); var callbackParam = Marshal.AllocHGlobal(IntPtr.Size * 2); unsafe { var ptr = (MINIDUMP_CALLBACK_INFORMATION *)callbackParam; ptr->CallbackRoutine = Marshal.GetFunctionPointerForDelegate(callbackDelegate); ptr->CallbackParam = IntPtr.Zero; } var minidumpFlags = MINIDUMP_TYPE.MiniDumpWithDataSegs | MINIDUMP_TYPE.MiniDumpWithTokenInformation | MINIDUMP_TYPE.MiniDumpWithPrivateWriteCopyMemory | MINIDUMP_TYPE.MiniDumpWithPrivateReadWriteMemory | MINIDUMP_TYPE.MiniDumpWithUnloadedModules | MINIDUMP_TYPE.MiniDumpWithFullMemory | MINIDUMP_TYPE.MiniDumpWithHandleData | MINIDUMP_TYPE.MiniDumpWithThreadInfo | MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo | MINIDUMP_TYPE.MiniDumpWithProcessThreadData | MINIDUMP_TYPE.MiniDumpWithModuleHeaders; hr = MiniDumpWriteDump(snapshotHandle, pid, fs.SafeFileHandle.DangerousGetHandle(), minidumpFlags, IntPtr.Zero, IntPtr.Zero, callbackParam); IntPtr vaCloneHandle; PssQuerySnapshot(snapshotHandle, PSS_QUERY_INFORMATION_CLASS.PSS_QUERY_VA_CLONE_INFORMATION, out vaCloneHandle, IntPtr.Size); var cloneProcessId = GetProcessId(vaCloneHandle); PssFreeSnapshot(Process.GetCurrentProcess().Handle, snapshotHandle); CloseHandle(vaCloneHandle); try { Process.GetProcessById(cloneProcessId).Kill(); } catch (Win32Exception) { } Marshal.FreeHGlobal(callbackParam); GC.KeepAlive(callbackDelegate); if (hr == 0) { Console.WriteLine($"MiniDumpWriteDump failed. ({Marshal.GetHRForLastWin32Error()})"); return(hr); } } sw.Stop(); Console.WriteLine($"Minidump Creation Time: {sw.ElapsedMilliseconds}ms"); return(0); }