
现在我准备创建一个简单的 winform 程序,在 button 事件中故意让主线程sleep造成程序假死,参考代码如下:
public partial class Form1 : Form { public Form1() { InitializeComponent()} private void button1_Click(object sender, EventArgs e) { Thread.Sleep(1000 * 10)MessageBox.Show("clicked me!")} }
接下来启动 cmd 窗口,输入:
C:\Windows\system32>procdump -ma -h -w WindowsFormsApp1.exe E:\net5\hungwindow.dmp ProcDump v10.0 - Sysinternals process dump utility Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards Sysinternals - www.sysinternals.com Waiting for process named WindowsFormsApp1.exe...
启动程序后点击 button 让 winform 假死,可以看到 procdump 在 5s 之后自动输出了dump。
using Systemusing System.Collections.Generic
using System.Text
using System.Runtime.InteropServices
using System.Diagnostics
using System.IO
using System.Threading
namespace MiniDump
...{
class Program
...{
static void Main(string[] args)
...{
try
...{
string a = ""
a = null
if (a.ToString() == "1")
Console.WriteLine("a is 1")
}
catch
...{
MiniDump.TryDump("c:MiniDmp.dmp", MiniDump.MiniDumpType.WithFullMemory)
}
Console.ReadKey()
}
}
/**//// <summary>
/// 该类要使用在windows 5.1 以后的版本,如果你的windows很旧,就把Windbg里面的dll拷贝过来,一般都没有问题
/// DbgHelp.dll 是windows自带的 dll文件 。
/// </summary>
public static class MiniDump
...{
/**//*
* 导入DbgHelp.dll
*/
[DllImport("DbgHelp.dll")]
private static extern Boolean MiniDumpWriteDump(
IntPtr hProcess,
Int32 processId,
IntPtr fileHandle,
MiniDumpType dumpType,
ref MinidumpExceptionInfo excepInfo,
IntPtr userInfo,
IntPtr extInfo )
/**//*
* MINIDUMP_EXCEPTION_INFORMATION 这个宏的信息
*/
struct MinidumpExceptionInfo
...{
public Int32 ThreadId
public IntPtr ExceptionPointers
public Boolean ClientPointers
}
/**//*
* 自己包装的一个函数
*/
public static Boolean TryDump(String dmpPath, MiniDumpType dmpType)
...{
//使用文件流来创健 .dmp文件
using (FileStream stream = new FileStream(dmpPath, FileMode.Create))
...{
//取得进程信息
Process process = Process.GetCurrentProcess()
// MINIDUMP_EXCEPTION_INFORMATION 信息的初始化
MinidumpExceptionInfo mei = new MinidumpExceptionInfo()
mei.ThreadId = Thread.CurrentThread.ManagedThreadId
mei.ExceptionPointers = Marshal.GetExceptionPointers()
mei.ClientPointers = true
//这里调用的Win32 API
Boolean res = MiniDumpWriteDump(
process.Handle,
process.Id,
stream.SafeFileHandle.DangerousGetHandle(),
dmpType,
ref mei,
IntPtr.Zero,
IntPtr.Zero)
//清空 stream
stream.Flush()
stream.Close()
return res
}
}
public enum MiniDumpType
...{
None = 0x00010000,
Normal = 0x00000000,
WithDataSegs = 0x00000001,
WithFullMemory = 0x00000002,
WithHandleData = 0x00000004,
FilterMemory = 0x00000008,
ScanMemory = 0x00000010,
WithUnloadedModules = 0x00000020,
WithIndirectlyReferencedMemory = 0x00000040,
FilterModulePaths = 0x00000080,
WithProcessThreadData = 0x00000100,
WithPrivateReadWriteMemory = 0x00000200,
WithoutOptionalData = 0x00000400,
WithFullMemoryInfo = 0x00000800,
WithThreadInfo = 0x00001000,
WithCodeSegs = 0x00002000
}
}
}
1. 进到 Control Panel -->System -->Advanced -->Startup/Recovery,请选complete memory dump并选中System Failure下的所有选项。请记住memory.dmp文件存放的位置,默认情况下此文件存放在%systemroot%下。请确认memory.dmp文件的存放路径下有足够的空间,即剩余空间大于等于物理内存的大小。如果默认目录下没有足够的空间,请把路径指定到有足够空间的分区的根目录下。2. 进到Control Panel -->System -->Advanced -->Performance Options -->Change。请确定pagefile是放在%systemroot%分区的。pagefile的大小需设置成比物理内存大,如,机器内存为1G,可以把pagefile文件的大小设成1100M。如果系统提示要重新启动服务器,请暂时不要重启。
3. 添加注册表键值:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters
Value Name: CrashOnCtrlScroll
Data Type: REG_DWORD
Value: 1
4. 重启计算机使设置生效。
5. 在问题再次发生时按住键盘右边的Ctrl键不放,再按两次ScrollLock键。如果设置正确,机器会立刻进入蓝屏,并开始将内存快照写入页面文件。您可以看到其完成进度。待其完成后,机器将会自动重启,并在重启后产生一个内存转储文件在 c:\windows\memory.dmp。
6. 对于某些笔记本没有右Ctrl键,可以通过导入附件的注册表文件来实现由左Ctrl *** 作产生Dump文件。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)