using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
-using System.Threading.Tasks;
namespace Microsoft.Diagnostics.Tools.Dump
{
{
private static class Windows
{
- internal static void CollectDump(Process process, string outputFile, DumpTypeOption type)
+ 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))
{
for (int i = 0; i < 5; i++)
{
// Dump the process!
- if (NativeMethods.MiniDumpWriteDump(process.Handle, (uint)process.Id, stream.SafeFileHandle, dumpType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
+ if (NativeMethods.MiniDumpWriteDump(processHandle.DangerousGetHandle(), (uint)processId, stream.SafeFileHandle, dumpType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
{
break;
}
{
public const int ERROR_PARTIAL_COPY = unchecked((int)0x8007012b);
+ public const int PROCESS_VM_READ = 0x0010;
+ public const int PROCESS_QUERY_INFORMATION = 0x0400;
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public extern static SafeProcessHandle OpenProcess(int access, [MarshalAs(UnmanagedType.Bool)] bool inherit, int processId);
+
[DllImport("Dbghelp.dll", SetLastError = true)]
- public static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeFileHandle hFile, MINIDUMP_TYPE DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
+ public extern static bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeFileHandle hFile, MINIDUMP_TYPE DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct MINIDUMP_EXCEPTION_INFORMATION
return 0;
}
- // Get the process
- Process process = Process.GetProcessById(processId);
-
- Windows.CollectDump(process, output, type);
+ Windows.CollectDump(processId, output, type);
}
else
{
}
catch (Exception ex) when
(ex is FileNotFoundException ||
+ ex is ArgumentException ||
ex is DirectoryNotFoundException ||
ex is UnauthorizedAccessException ||
ex is PlatformNotSupportedException ||