Skip to content

Commit

Permalink
Writes Minidump when crashing. Fixes #48.
Browse files Browse the repository at this point in the history
Also put it in the ZIP
  • Loading branch information
Antoine Aflalo committed Dec 27, 2015
1 parent 29cc834 commit b744f87
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 6 deletions.
182 changes: 182 additions & 0 deletions SoundSwitch/Framework/Minidump/MemoryDumper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace SoundSwitch.Framework.Minidump
{
public static class MiniDump

{
public enum ExceptionInfo

{
None,

Present
}

// 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
}


//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)]
private 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)]
private 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)]
private static extern uint GetCurrentThreadId();


public static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo)

{
var currentProcess = Process.GetCurrentProcess();

var currentProcessHandle = currentProcess.Handle;

var currentProcessId = (uint) currentProcess.Id;

MiniDumpExceptionInformation exp;

exp.ThreadId = GetCurrentThreadId();

exp.ClientPointers = false;

exp.ExceptionPointers = IntPtr.Zero;

if (exceptionInfo == ExceptionInfo.Present)

{
exp.ExceptionPointers = Marshal.GetExceptionPointers();
}

var bRet = false;

if (exp.ExceptionPointers == IntPtr.Zero)

{
bRet = MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero);
}

else

{
bRet = MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, ref exp,
IntPtr.Zero, IntPtr.Zero);
}

return bRet;
}


public static bool Write(SafeHandle fileHandle, Option dumpType)

{
return Write(fileHandle, dumpType, ExceptionInfo.None);
}


//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!
public struct MiniDumpExceptionInformation

{
public uint ThreadId;

public IntPtr ExceptionPointers;

[MarshalAs(UnmanagedType.Bool)] public bool ClientPointers;
}
}
}
27 changes: 21 additions & 6 deletions SoundSwitch/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using AudioEndPointControllerWrapper;
using SoundSwitch.Framework;
using SoundSwitch.Framework.Configuration;
using SoundSwitch.Framework.Minidump;
using SoundSwitch.Model;
using SoundSwitch.Util;

Expand Down Expand Up @@ -115,7 +116,8 @@ private static void Application_ThreadException(object sender, ThreadExceptionEv

private static void HandleException(Exception exception)
{
AppLogger.Log.Fatal("Exception Occured ", exception);
if (exception == null)
return;
var zipFile = Path.Combine(ApplicationPath.AppData,
$"{Application.ProductName}-crashlog-{DateTime.UtcNow.Date.Day}_{DateTime.UtcNow.Date.Month}_{DateTime.UtcNow.Date.Year}.zip");
var message =
Expand All @@ -129,15 +131,28 @@ private static void HandleException(Exception exception)
if (result == DialogResult.Yes)
{
using (new HourGlass())
using (new AppLogger.LogRestartor())
{
if (File.Exists(zipFile))
var fileName = Path.Combine(ApplicationPath.Default, Environment.MachineName + ".dmp");
using (
var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite,
FileShare.Write))
{
File.Delete(zipFile);
MiniDump.Write(fs.SafeFileHandle,
MiniDump.Option.Normal | MiniDump.Option.WithThreadInfo | MiniDump.Option.WithHandleData |
MiniDump.Option.WithDataSegs, MiniDump.ExceptionInfo.Present);
}
ZipFile.CreateFromDirectory(ApplicationPath.Default, zipFile);
AppLogger.Log.Fatal("Exception Occured ", exception);
using (new AppLogger.LogRestartor())
{
if (File.Exists(zipFile))
{
File.Delete(zipFile);
}

ZipFile.CreateFromDirectory(ApplicationPath.Default, zipFile);
}
Process.Start("explorer.exe", "/select," + @zipFile);
}
Process.Start("explorer.exe", "/select," + @zipFile);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions SoundSwitch/SoundSwitch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
<Compile Include="Framework\ApplicationPath.cs" />
<Compile Include="Framework\Configuration\AppConfigs.cs" />
<Compile Include="Framework\HourGlass.cs" />
<Compile Include="Framework\Minidump\MemoryDumper.cs" />
<Compile Include="Model\IAudioDeviceLister.cs" />
<Compile Include="Properties\AboutStrings.Designer.cs">
<AutoGen>True</AutoGen>
Expand Down

0 comments on commit b744f87

Please sign in to comment.