c# - dmp - minidump windows 10
Tomando volcado de memoria utilizando C# (3)
Tengo un objeto System.Diagnostics.Process
. Mi programa de C # lo está monitoreando por alguna condición. Cuando se alcanza la condición, quiero tomar un volcado de memoria completa del Proceso.
¿Cuál es la mejor manera de lograr esto?
¿Hay alguna manera que es proporcionada por el CLR ?
Puede usar ProcDump desde Sysinternals y hacer que su programa C # lo llame cuando sea necesario.
Process.Start("procdump " + otherProgramPID.ToString());
Puedes intentar llamar al método C ++ desde tu código C #. Aquí hay un ejemplo de cómo lo declararías:
[DllImport("dbghelp.dll",
EntryPoint = "MiniDumpWriteDump",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
MINIDUMP_TYPE dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
Puede consultar el código de este proyecto para ver un ejemplo: https://github.com/projectkudu/kudu/blob/master/Kudu.Core/Infrastructure/MiniDumpNativeMethods.cs https://github.com/projectkudu/kudu/blob/2db563be679bb60656050ec3f04945086f07b360/Kudu.Core/Infrastructure/ProcessExtensions.cs
Microsofts MSDN muestra un ejemplo de código sobre cómo lograr esto utilizando el código C # dentro de su propia aplicación:
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
// !load //ddelementary/autowatson/vsdbg/vsdbg.dll
namespace CreateMiniDump
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += (ol, el) =>
{
IntPtr hFile = IntPtr.Zero;
try
{
if (IntPtr.Size == 4)
{
this.Title = "CreateMiniDump Running as 32 bit, creating 32 bit dumps";
}
else
{
this.Title = "CreateMiniDump Running as 64 bit, creating 64 bit dumps";
}
this.Height = 800;
this.Width = 800;
var sp = new StackPanel() { Orientation = Orientation.Vertical };
this.Content = sp;
var dumpFileName = System.IO.Path.Combine(
System.IO.Path.GetTempPath(),
"testdump.dmp");
var txtDumpFile = new TextBox()
{
Text = dumpFileName
};
sp.Children.Add(txtDumpFile);
var txtProcName = new TextBox()
{
ToolTip = "Process name without extension",
Text = "devenv"
};
sp.Children.Add(txtProcName);
var lstDumpType = new ListBox()
{
// allow multi select
SelectionMode = SelectionMode.Extended
};
lstDumpType.ItemsSource = Enum.GetValues(typeof(NativeMethods._MINIDUMP_TYPE));
// set initial value
// for a dump with memory info we want these:
foreach (var val in new[] {
NativeMethods._MINIDUMP_TYPE.MiniDumpWithFullMemory,
NativeMethods._MINIDUMP_TYPE.MiniDumpWithFullMemoryInfo,
NativeMethods._MINIDUMP_TYPE.MiniDumpWithHandleData,
NativeMethods._MINIDUMP_TYPE.MiniDumpWithThreadInfo
})
{
var nval = (int)(Math.Log((int)val) / Math.Log(2)) + 1;
lstDumpType.SelectedItems.Add(
lstDumpType.Items[nval]
);
}
sp.Children.Add(lstDumpType);
var btnGo = new Button()
{
Content = "_Create Dump",
Width = 200
};
sp.Children.Add(btnGo);
var txtStatus = new TextBox()
{
IsUndoEnabled = false,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
MaxHeight = 400
};
sp.Children.Add(txtStatus);
btnGo.Click += (ob, eb) =>
{
try
{
var sw = new Stopwatch();
sw.Start();
dumpFileName = txtDumpFile.Text.Trim();
if (System.IO.File.Exists(dumpFileName))
{
System.IO.File.Delete(dumpFileName);
}
hFile = NativeMethods.CreateFile(
dumpFileName,
NativeMethods.EFileAccess.GenericWrite,
NativeMethods.EFileShare.None,
lpSecurityAttributes: IntPtr.Zero,
dwCreationDisposition: NativeMethods.ECreationDisposition.CreateAlways,
dwFlagsAndAttributes: NativeMethods.EFileAttributes.Normal,
hTemplateFile: IntPtr.Zero
);
if (hFile == NativeMethods.INVALID_HANDLE_VALUE)
{
var hr = Marshal.GetHRForLastWin32Error();
var ex = Marshal.GetExceptionForHR(hr);
throw ex;
}
NativeMethods._MINIDUMP_TYPE dumpType = NativeMethods._MINIDUMP_TYPE.MiniDumpNormal; // 0
foreach (var item in lstDumpType.SelectedItems)
{
var dt = (NativeMethods._MINIDUMP_TYPE)item;
dumpType |= dt;
}
var exceptInfo = new NativeMethods.MINIDUMP_EXCEPTION_INFORMATION();
var proc = Process.GetProcessesByName(
txtProcName.Text.Trim()
).FirstOrDefault();
if (!proc.Is32BitProcess() && IntPtr.Size == 4)
{
throw new InvalidOperationException(
"Can''t create 32 bit dump of 64 bit process"
);
}
var result = NativeMethods.MiniDumpWriteDump(
proc.Handle,
proc.Id,
hFile,
dumpType,
ref exceptInfo,
UserStreamParam: IntPtr.Zero,
CallbackParam: IntPtr.Zero
);
if (result == false)
{
var hr = Marshal.GetHRForLastWin32Error();
var ex = Marshal.GetExceptionForHR(hr);
throw ex;
}
txtStatus.Text = string.Format(
"Dump Created. Pid= {0} {1}/r File size = {2:n0}/rElapsed = {3:n3}/r",
proc.Id,
dumpType,
(new System.IO.FileInfo(dumpFileName)).Length,
sw.Elapsed.TotalSeconds
);
}
catch (Exception ex)
{
txtStatus.Text = ex.ToString();
}
finally
{
NativeMethods.CloseHandle(hFile);
}
};
}
catch (Exception ex)
{
this.Content = ex.ToString();
}
};
}
}
public static class ExtensionMethods
{
public static bool Is32BitProcess(this Process proc)
{
bool fIs32bit = false;
// if we''re runing on 32bit, default to true
if (IntPtr.Size == 4)
{
fIs32bit = true;
}
bool fIsRunningUnderWow64 = false;
// if machine is 32 bit then all procs are 32 bit
if (NativeMethods.IsWow64Process(NativeMethods.GetCurrentProcess(), out fIsRunningUnderWow64)
&& fIsRunningUnderWow64)
{
// current OS is 64 bit
if (NativeMethods.IsWow64Process(proc.Handle, out fIsRunningUnderWow64)
&& fIsRunningUnderWow64)
{
fIs32bit = true;
}
else
{
fIs32bit = false;
}
}
return fIs32bit;
}
}
public static partial class NativeMethods
{
[DllImport("Dbghelp.dll")]
public static extern bool MiniDumpWriteDump(
IntPtr hProcess,
int ProcessId,
IntPtr hFile,
_MINIDUMP_TYPE DumpType,
ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
IntPtr UserStreamParam,
IntPtr CallbackParam
);
//https://msdn.microsoft.com/en-us/library/windows/desktop/ms680519%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
[Flags]
public enum _MINIDUMP_TYPE
{
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
MiniDumpWithFullMemory = 0x00000002,
MiniDumpWithHandleData = 0x00000004,
MiniDumpFilterMemory = 0x00000008,
MiniDumpScanMemory = 0x00000010,
MiniDumpWithUnloadedModules = 0x00000020,
MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
MiniDumpFilterModulePaths = 0x00000080,
MiniDumpWithProcessThreadData = 0x00000100,
MiniDumpWithPrivateReadWriteMemory = 0x00000200,
MiniDumpWithoutOptionalData = 0x00000400,
MiniDumpWithFullMemoryInfo = 0x00000800,
MiniDumpWithThreadInfo = 0x00001000,
MiniDumpWithCodeSegs = 0x00002000,
MiniDumpWithoutAuxiliaryState = 0x00004000,
MiniDumpWithFullAuxiliaryState = 0x00008000,
MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
MiniDumpIgnoreInaccessibleMemory = 0x00020000,
MiniDumpWithTokenInformation = 0x00040000,
MiniDumpWithModuleHeaders = 0x00080000,
MiniDumpFilterTriage = 0x00100000,
MiniDumpValidTypeFlags = 0x001fffff,
};
/*
*
https://msdn.microsoft.com/en-us/library/windows/desktop/bb513622(v=vs.85).aspx
WER_DUMP_TYPE:
WerDumpTypeHeapDump
MiniDumpWithDataSegs
MiniDumpWithProcessThreadData
MiniDumpWithHandleData
MiniDumpWithPrivateReadWriteMemory
MiniDumpWithUnloadedModules
MiniDumpWithFullMemoryInfo
MiniDumpWithThreadInfo (Windows 7 and later)
MiniDumpWithTokenInformation (Windows 7 and later)
MiniDumpWithPrivateWriteCopyMemory
WerDumpTypeMicroDump
MiniDumpWithDataSegs
MiniDumpWithUnloadedModules
MiniDumpWithProcessThreadData
MiniDumpWithoutOptionalData
WerDumpTypeMiniDump
MiniDumpWithDataSegs
MiniDumpWithUnloadedModules
MiniDumpWithProcessThreadData
MiniDumpWithTokenInformation
*/
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct MINIDUMP_EXCEPTION_INFORMATION
{
public uint ThreadId;
public IntPtr ExceptionPointers;
public int ClientPointers;
}
[DllImport("kernel32.dll",
SetLastError = true,
CharSet = CharSet.Auto)]
public static extern IntPtr CreateFile(
string lpFileName,
EFileAccess dwDesiredAccess,
EFileShare dwShareMode,
IntPtr lpSecurityAttributes,
ECreationDisposition dwCreationDisposition,
EFileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll",
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[Flags]
public enum EFileAccess : uint
{
//
// Standart Section
//
AccessSystemSecurity = 0x1000000, // AccessSystemAcl access type
MaximumAllowed = 0x2000000, // MaximumAllowed access type
Delete = 0x10000,
ReadControl = 0x20000,
WriteDAC = 0x40000,
WriteOwner = 0x80000,
Synchronize = 0x100000,
StandardRightsRequired = 0xF0000,
StandardRightsRead = ReadControl,
StandardRightsWrite = ReadControl,
StandardRightsExecute = ReadControl,
StandardRightsAll = 0x1F0000,
SpecificRightsAll = 0xFFFF,
FILE_READ_DATA = 0x0001, // file & pipe
FILE_LIST_DIRECTORY = 0x0001, // directory
FILE_WRITE_DATA = 0x0002, // file & pipe
FILE_ADD_FILE = 0x0002, // directory
FILE_APPEND_DATA = 0x0004, // file
FILE_ADD_SUBDIRECTORY = 0x0004, // directory
FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe
FILE_READ_EA = 0x0008, // file & directory
FILE_WRITE_EA = 0x0010, // file & directory
FILE_EXECUTE = 0x0020, // file
FILE_TRAVERSE = 0x0020, // directory
FILE_DELETE_CHILD = 0x0040, // directory
FILE_READ_ATTRIBUTES = 0x0080, // all
FILE_WRITE_ATTRIBUTES = 0x0100, // all
//
// Generic Section
//
GenericRead = 0x80000000,
GenericWrite = 0x40000000,
GenericExecute = 0x20000000,
GenericAll = 0x10000000,
SPECIFIC_RIGHTS_ALL = 0x00FFFF,
FILE_ALL_ACCESS =
StandardRightsRequired |
Synchronize |
0x1FF,
FILE_GENERIC_READ =
StandardRightsRead |
FILE_READ_DATA |
FILE_READ_ATTRIBUTES |
FILE_READ_EA |
Synchronize,
FILE_GENERIC_WRITE =
StandardRightsWrite |
FILE_WRITE_DATA |
FILE_WRITE_ATTRIBUTES |
FILE_WRITE_EA |
FILE_APPEND_DATA |
Synchronize,
FILE_GENERIC_EXECUTE =
StandardRightsExecute |
FILE_READ_ATTRIBUTES |
FILE_EXECUTE |
Synchronize
}
[Flags]
public enum EFileShare : uint
{
/// <summary>
///
/// </summary>
None = 0x00000000,
/// <summary>
/// Enables subsequent open operations on an object to request read access.
/// Otherwise, other processes cannot open the object if they request read access.
/// If this flag is not specified, but the object has been opened for read access, the function fails.
/// </summary>
Read = 0x00000001,
/// <summary>
/// Enables subsequent open operations on an object to request write access.
/// Otherwise, other processes cannot open the object if they request write access.
/// If this flag is not specified, but the object has been opened for write access, the function fails.
/// </summary>
Write = 0x00000002,
/// <summary>
/// Enables subsequent open operations on an object to request delete access.
/// Otherwise, other processes cannot open the object if they request delete access.
/// If this flag is not specified, but the object has been opened for delete access, the function fails.
/// </summary>
Delete = 0x00000004
}
public enum ECreationDisposition : uint
{
/// <summary>
/// Creates a new file. The function fails if a specified file exists.
/// </summary>
New = 1,
/// <summary>
/// Creates a new file, always.
/// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes,
/// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
/// </summary>
CreateAlways = 2,
/// <summary>
/// Opens a file. The function fails if the file does not exist.
/// </summary>
OpenExisting = 3,
/// <summary>
/// Opens a file, always.
/// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
/// </summary>
OpenAlways = 4,
/// <summary>
/// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
/// The calling process must open the file with the GENERIC_WRITE access right.
/// </summary>
TruncateExisting = 5
}
[Flags]
public enum EFileAttributes : uint
{
Readonly = 0x00000001,
Hidden = 0x00000002,
System = 0x00000004,
Directory = 0x00000010,
Archive = 0x00000020,
Device = 0x00000040,
Normal = 0x00000080,
Temporary = 0x00000100,
SparseFile = 0x00000200,
ReparsePoint = 0x00000400,
Compressed = 0x00000800,
Offline = 0x00001000,
NotContentIndexed = 0x00002000,
Encrypted = 0x00004000,
Write_Through = 0x80000000,
Overlapped = 0x40000000,
NoBuffering = 0x20000000,
RandomAccess = 0x10000000,
SequentialScan = 0x08000000,
DeleteOnClose = 0x04000000,
BackupSemantics = 0x02000000,
PosixSemantics = 0x01000000,
OpenReparsePoint = 0x00200000,
OpenNoRecall = 0x00100000,
FirstPipeInstance = 0x00080000
}
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process(
[In] IntPtr hProcess,
[Out, MarshalAs(UnmanagedType.Bool)] out bool wow64Process
);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
}
}