1. 程式人生 > 其它 >C# 程式退出 自動生成 記憶體快照 Dump檔案

C# 程式退出 自動生成 記憶體快照 Dump檔案

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;

namespace _2021_09_22_生成dmp檔案
{
    class Program
    {
        static void AutoGenerateDumpWhenCrash()
        {

            //參考文件:https://docs.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps?redirectedfrom=MSDN 

            //登錄檔裡,新增【程式崩潰後,自動生成dump檔案配置】
            //登錄檔需要admin許可權!
            try
            {
                var outputDmpPath = AppDomain.CurrentDomain.BaseDirectory + "Dump";
                if (!Directory.Exists(outputDmpPath))
                {
                    Directory.CreateDirectory(outputDmpPath);
                }

                var fileName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
                var processName = fileName.Substring(fileName.LastIndexOf('\\') + 1);

                //登錄檔地址
                string regPath = @"SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\" + processName;
                var reg = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);//Registry64防止登錄檔重定向到wow64

                var subKey = reg.CreateSubKey(regPath);



                subKey.SetValue("DumpCount", 1, RegistryValueKind.DWord);//dump檔案個數
                subKey.SetValue("DumpFolder", outputDmpPath, RegistryValueKind.ExpandString);//dump檔案目錄
                subKey.SetValue("DumpType", 1, RegistryValueKind.DWord);//dump檔案型別

            }
            catch (Exception ex)
            {
                //CLoggerTools.Warning2File(CLoggerFileName.strException, "{0},{1},{2}", "UI.Program", ex.Message, ex.StackTrace.Replace("\r\n", ""));
                return;
            }


        }
        static void Main(string[] args)
        {

           AutoGenerateDumpWhenCrash();






            //try
            //{
            string a = "";
            a = null;
            if (a.ToString() == "1")
                Console.WriteLine("a is 1");
            // }
            //catch
            //{
            //    MiniDump.TryDump("c:MiniDmp.dmp", MiniDump.Option.WithFullMemory);
            //}
            Console.ReadKey();
        }
    }
}

  

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace _2021_09_22_生成dmp檔案
{
    public static class MiniDump
    {
        // Taken almost verbatim from 
http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/ [Flags] public enum Option : uint { // From dbghelp.h: 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, WithoutAuxiliaryState = 0x00004000, WithFullAuxiliaryState = 0x00008000, WithPrivateWriteCopyMemory = 0x00010000, IgnoreInaccessibleMemory = 0x00020000, ValidTypeFlags = 0x0003ffff, } enum ExceptionInfo { None, Present } //typedef struct _MINIDUMP_EXCEPTION_INFORMATION { // DWORD ThreadId; // PEXCEPTION_POINTERS ExceptionPointers; // BOOL ClientPointers; //} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; [StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64! struct MiniDumpExceptionInformation { public uint ThreadId; public IntPtr ExceptionPointers; [MarshalAs(UnmanagedType.Bool)] public bool ClientPointers; } //BOOL //WINAPI //MiniDumpWriteDump( // __in HANDLE hProcess, // __in DWORD ProcessId, // __in HANDLE hFile, // __in MINIDUMP_TYPE DumpType, // __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, // __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, // __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam // ); // Overload requiring MiniDumpExceptionInformation [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam); // Overload supporting MiniDumpExceptionInformation == NULL [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam); [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] static extern uint GetCurrentThreadId(); static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo) { Process currentProcess = Process.GetCurrentProcess(); IntPtr currentProcessHandle = currentProcess.Handle; uint currentProcessId = (uint)currentProcess.Id; MiniDumpExceptionInformation exp; exp.ThreadId = GetCurrentThreadId(); exp.ClientPointers = false; exp.ExceptionPointers = IntPtr.Zero; if (exceptionInfo == ExceptionInfo.Present) { exp.ExceptionPointers = Marshal.GetExceptionPointers(); } return exp.ExceptionPointers == IntPtr.Zero ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) : MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero); } static bool Write(SafeHandle fileHandle, Option dumpType) { return Write(fileHandle, dumpType, ExceptionInfo.None); } public static Boolean TryDump(String dmpPath, Option dmpType = Option.Normal) { var path = Path.Combine(Environment.CurrentDirectory, dmpPath); var dir = Path.GetDirectoryName(path); if (dir != null && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } using (var fs = new FileStream(path, FileMode.Create)) { return Write(fs.SafeFileHandle, dmpType); } } } }