Click here to Skip to main content
15,913,722 members
Articles / Programming Languages / C#
Tip/Trick

Automatically Create Dump File When Program Hangs

Rate me:
Please Sign up or sign in to vote.
4.00/5 (6 votes)
24 Jan 2019CPOL 10K   15   3
How to automatically create a dump file when the program hangs

Introduction

I would like to know how to create a dump file automatically when my program hangs for unexpected exceptions.

Background

There were a lot of articles about how to create a dump file using the Window Command or the Windbg program.

But my program is already set into a customer's computer, so I can't tell him "You should make a dump file yourself when the program is not responding."

Using the Code

To run this program, you need to use cdb.exe file. You can find in the attachment file. or You can download it as "Windows Software Development Kit" on the internet. While installing it, you should check the item "Debuggin Tools for Windows". Those files are inclued in that. You can also use windbg.exe file instead of cdb.exe. if you use it, windbg window will open and run.

C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace ProcessHangCheck
{
    public partial class Form1 : Form
    {
        Thread mThread;
        Process mProcess;

        public Form1()
        {
            InitializeComponent();
            mThread = null;
            mProcess = null;
        }

        // start monitoring 
        private void button1_Click(object sender, EventArgs e)
        {
            // process name except for ".exe"
            String strProcName = txtProcName.Text;

            // the execution file which is place in (like cdb or windbg)
            String strDumpExePath = txtDumpExecutionPath.Text;

            // the directory place in which a dump file is created
            String strDumpPath = txtDumpPath.Text;

            try
            {
                strDumpExePath = Path.GetFullPath(strDumpExePath);
                strDumpPath = Path.GetFullPath(strDumpPath);

                if (!Directory.Exists(strDumpExePath))
                    Directory.CreateDirectory(strDumpExePath);

                if (!Directory.Exists(strDumpPath))
                    Directory.CreateDirectory(strDumpPath);
            }
            catch (Exception)
            {
                strDumpExePath = "";
                strDumpPath = "";
            }

            if (String.IsNullOrEmpty(strProcName) ||
                String.IsNullOrEmpty(strDumpExePath) ||
                String.IsNullOrEmpty(strDumpPath))
            {
                MessageBox.Show("Process Name or CDB's location or Dump's directory is empty.");
            }
            else
            {
                Stop();
                mThread = new Thread(() => threadMain(strProcName, strDumpExePath, strDumpPath));
                mThread.Start();
            }
        }

        private void threadMain(String strProcName, String strDumpExePath, String strDumpPath)
        {
            if (String.IsNullOrEmpty(strProcName) || 
                String.IsNullOrEmpty(strDumpExePath) || String.IsNullOrEmpty(strDumpPath)) return;

            bool isAbort = false;
            while (!isAbort)
            {
                try
                {
                    Process[] procs = Process.GetProcessesByName(strProcName);
                    if (procs.Length != 0)
                    {
                        foreach (Process pr in procs)
                        {
                            // if this process is hanging
                            if (!pr.Responding)
                            {
                                Console.WriteLine("Start trying to create a dumpfile");

                                try
                                {
                                    strDumpExePath += "\\";
                                    strDumpExePath = Path.GetFullPath(strDumpExePath);

                                    strDumpPath += "\\";
                                    strDumpPath = Path.GetFullPath(strDumpPath);

                                    String strCmdParam = String.Format(
                                            "-p {0} -c \".dump /o /ma {1}{2}.dmp\"",
                                            pr.Id,
                                            strDumpPath,
                                            DateTime.Now.ToString("yyyyMMddHHmmss"));
                                    Console.WriteLine(strCmdParam);

                                    mProcess = new Process();

                                    mProcess.StartInfo.FileName = "cmd.exe";
                                    mProcess.StartInfo.UseShellExecute = false;
                                    mProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                                    mProcess.StartInfo.CreateNoWindow = true;
                                    mProcess.StartInfo.RedirectStandardOutput = true;
                                    mProcess.StartInfo.RedirectStandardInput = true;
                                    mProcess.StartInfo.RedirectStandardError = true;
                                    mProcess.Start();
                                    mProcess.StandardInput.WriteLine(
                                        String.Format(
                                            "\"{0}cdb.exe\" -p {1} -c \".dump /o /ma {2}{3}.dmp\"{4}",
                                            strDumpExePath,
                                            pr.Id,
                                            strDumpPath,
                                            DateTime.Now.ToString("yyyyMMddHHmmss"),
                                            Environment.NewLine));

                                    mProcess.StandardInput.Close();
                                    String strOutput = mProcess.StandardOutput.ReadToEnd();
                                    Console.WriteLine(strOutput);

                                    mProcess.WaitForExit(10 * 1000);
                                    if (!mProcess.HasExited) mProcess.Kill();

                                    if (!pr.HasExited) pr.Kill();
                                }
                                catch(Exception ex)
                                {
                                    MessageBox.Show(ex.ToString());
                                }
                            }
                            else
                            {
                                Console.WriteLine("Noting to do");
                            }
                        }
                    }
                    else
                        Console.WriteLine("Process isn't running");

                    Thread.Sleep(10 * 1000);
                }
                catch(ThreadAbortException)
                {
                    isAbort = true;
                    Thread.ResetAbort();
                }
                catch (Exception ee)
                {
                    Console.WriteLine(ee.ToString());
                    Thread.Sleep(10 * 1000);
                }
            }
        }

        private void Stop()
        {
            try
            {
                if (mThread != null)
                    mThread.Abort();

                if (mProcess != null && !mProcess.HasExited)
                    mProcess.Kill();
            }
            catch (Exception) { }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Stop();
        }

        // stop monitoring
        private void button2_Click(object sender, EventArgs e)
        {
            Stop();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            String strRoot = Application.StartupPath;
            txtDumpExecutionPath.Text = String.Format("{0}\\USEEXE", strRoot);
        }
    }
}

Points of Interest

There is no program which is perfect. :)

History

  • 24th January, 2019: Initial version
  • 25th January, 2019: zip file attached and add comments

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Wiseneosco
Korea (Republic of) Korea (Republic of)
You know I can't speak English well but I'm learning. If there anything wrong in my article. Understand me. Smile | :) I'm so thankful if you could correct this.
Anyway, I'm a software programmer in Korea. I have been doing development about 10 years.
I majored in Computer Science and Engineering. I'm using c# mainly. Bye!

Comments and Discussions

 
Questioncdb.exe? Pin
dandy7224-Jan-19 5:03
dandy7224-Jan-19 5:03 
Quote:
There were a lot of articles about how to create a dump file using the Window Command or the Windbg program.

But my program is already set into a customer's computer, so I can't tell him "You should make a dump file yourself when the program is not responding."


...yet your program invokes cdb.exe, which most users won't have.

Perhaps it'd be worth mentioning where developers (those who'd like to use your code) are expected to find this .exe and whether it's got any external dependencies of its own. Then one might be able to decide whether cdb.exe could perhaps be bundled with their application, or better yet, embedded as a resource that could be extracted as needed. But if there's multiple MBs worth of dependencies, then that might be a non-starter. Having this sort of information in your article would help make that decision.
PraiseRe: cdb.exe? Pin
Bloody Chicken24-Jan-19 15:41
professionalBloody Chicken24-Jan-19 15:41 
GeneralRe: cdb.exe? Pin
dandy7225-Jan-19 7:53
dandy7225-Jan-19 7:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.