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.
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;
}
private void button1_Click(object sender, EventArgs e)
{
String strProcName = txtProcName.Text;
String strDumpExePath = txtDumpExecutionPath.Text;
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 (!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();
}
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