An Introduction to Collecting Windows Crash Dumps - WER/ProcDump/WinDbg
· Updated: · Go Komura · Windows Development, Bug Investigation, Crash Dump, WER, ProcDump, WinDbg
Revision history (2 updates, last updated Sep 1, 2026)
A log of the changes made to this article. Where a pre-update version was archived, it stays readable at a permanent DOI link.
- Retranslated as a full translation of the Japanese original. The previous English version was an abridgement that carried only part of the source, so sections, tables, Mermaid diagrams, figure captions and FAQ entries were missing. All of them have been restored to match the Japanese original, and the technical claims are the same as in the Japanese version.
- Fixed a display problem where lines containing a vertical bar were rendered as a table, leaving the reference links unclickable. The text itself is unchanged.
- First published
Cite this article(DOI: 10.5281/zenodo.21614520)
This article is archived on Zenodo. Below are both the DOI that always resolves to the latest version and the DOI pinned to the version you are reading.
Go Komura (2026). An Introduction to Collecting Windows Crash Dumps - WER/ProcDump/WinDbg. KomuraSoft LLC. https://doi.org/10.5281/zenodo.21614520 https://comcomponent.com/en/blog/2026/03/16/008-windows-app-crash-dump-collection-introduction/
- DOI (latest version)
- 10.5281/zenodo.21614520
- DOI (this version)
- 10.5281/zenodo.22217160
Once a Windows application starts crashing “only occasionally,” there are plenty of situations where logs alone are not enough to track it down.
The really painful cases look like this.
- It only happens in the customer’s environment
- You have the exception message, but not enough context about the caller
- It involves not just the managed side of C# / .NET, but also COM, P/Invoke, native DLLs, and vendor SDKs
- It only crashes after long hours of continuous operation
This is where crash dumps are effective. If you write the process state at the moment of the crash out to a file, you can later read the exception code, the stack of the crashing thread, the loaded modules, and part or all of memory.
On Windows, the easiest way to think about it is in this order: start with WER LocalDumps, add Sysinternals ProcDump when needed, and reach for MiniDumpWriteDump once you want even more control. In this article, we lay out the first steps of crash dump collection, assuming Windows desktop applications, resident applications, Windows services, equipment-integration tools, and the like.
flowchart TB
accTitle: The order in which to consider collection methods
accDescr: Diagram showing that Windows crash dump collection is easiest to reason about in the order of WER LocalDumps first, Sysinternals ProcDump when needed, and MiniDumpWriteDump when you want even more control.
w1["Start with WER LocalDumps"] --> w2["Add ProcDump when needed"]
w2 --> w3["MiniDumpWriteDump if you want more control"]
Figure 1: Start with the built-in feature and add tools only where it falls short.
Terms That Come Up Repeatedly in This Article
Let’s pin these down briefly up front. If they stay vague, the later sections blur.
| Term | Meaning |
|---|---|
| PDB | The debug information file generated at build time. It is the mapping table used to turn addresses back into function names and line numbers |
| Symbols | The correspondence between addresses and names. Supplied from PDBs or a symbol server. Without them, a call stack is nothing but a list of addresses |
| first chance exception | The stage just after an exception is raised, before the application’s exception handler has processed it. If the application catches it, execution simply continues |
| second chance exception | The stage where the application fails to handle it and the process heads for termination as an unhandled exception. This is what people normally mean by “it crashed” |
| postmortem debugger | A debugger that the OS launches automatically when a crash happens. It is registered as machine-wide crash-time behavior |
| Minidump / full dump | The difference in how much memory the dump contains. Covered in section 7 |
1. The Conclusions First
Let’s start with just the points you want to lock in first.
- The safe first move is to configure WER LocalDumps per application. With no extra tools, you get a dump saved locally after a crash.
- Use ProcDump for field investigations with a low reproduction rate, or when you also want to see first chance exceptions and hangs.
- Treat custom collection as the last thing to consider — that is about the right level. It is enough to look at
MiniDumpWriteDumponce you actually need it. - Just as important as the dumps themselves is keeping the PDBs and the shipped binaries. With a dump but no symbols, how much you can read drops considerably.
- Full dumps are powerful, but so are their size and the risk of pulling in confidential data. Decide the storage location, retention count, access rights, and sharing procedure up front.
At the introductory stage, the recommended setup usually lands around here.
| Environment | First setup |
|---|---|
| Dev machine / test machine | Configure WER LocalDumps per application, starting with full dumps via DumpType=2 |
| Customer environment / field machine | Choose DumpType=1 or 2 based on disk space and confidentiality requirements. Add ProcDump only when needed |
| Long-running operation or hang investigation | In addition to WER, consider ProcDump’s -h or -e 1 |
| You also want a custom UI or attached logs | Custom collection using MiniDumpWriteDump, assuming a separate process |
In short: WER first, then ProcDump, and custom collection last. Start in the reverse order and the design usually ends up heavier than it needs to be.
Knowledge map for this article
For crash dump collection in a Windows app, the safe order to think in is to first put WER LocalDumps in place, which can be configured per application without any extra tools, then add ProcDump when hangs or first chance exceptions also have to be observed or when an already running process needs to be monitored, and only consider collecting dumps yourself with MiniDumpWriteDump once a custom diagnostic feature becomes necessary. For the dump type, a minidump and a full dump trade the depth of the information they capture against size, and a .NET CLR process produces a dump the size of a full dump even when MiniPlus is specified for ProcDump. Unless write permission on the output folder is checked, the collection itself comes up empty, and a dump that has been captured only becomes readable information once it is analyzed in WinDbg in combination with PDBs.
flowchart LR
accTitle: Windows crash dump collection (WER/ProcDump/WinDbg)
accDescr: Diagram showing that WER LocalDumps, ProcDump, and MiniDumpWriteDump are the crash dump collection options to consider in that order, and that choosing the dump type, checking the ACL on the output folder, and analyzing the dump in WinDbg together with PDBs form one continuous flow
wer_localdumps["WER LocalDumps"]
procdump["ProcDump"]
windbg["WinDbg"]
minidumpwritedump["MiniDumpWriteDump"]
crash_dump["Crash dump"]
minidump["Minidump"]
fulldump["Full Dump"]
miniplus_dump["MiniPlus Dump"]
native_boundary_crash_investigation["Native Boundary Crash Investigation"]
dump_folder_acl["Dump Folder ACL"]
first_chance_exception["First Chance Exception"]
second_chance_exception["Second Chance Exception"]
hang_detection["Hang Detection"]
postmortem_debugger["Postmortem Debugger"]
pdb["PDB (Program Database)"]
custom_diagnostic_report["Custom diagnostic report feature"]
notmyfault["NotMyFault"]
wer_localdumps -->|"should come before"| procdump
procdump -->|"should come before"| minidumpwritedump
wer_localdumps -->|"implements"| crash_dump
procdump -->|"implements"| crash_dump
wer_localdumps -.->|"uses"| minidump
wer_localdumps -.->|"uses"| fulldump
procdump -.->|"uses"| fulldump
procdump -.->|"uses"| miniplus_dump
fulldump -->|"recommended for"| native_boundary_crash_investigation
minidump -->|"not recommended for"| native_boundary_crash_investigation
wer_localdumps -.->|"requires"| dump_folder_acl
procdump -.->|"uses"| first_chance_exception
procdump -.->|"uses"| second_chance_exception
procdump -.->|"uses"| hang_detection
wer_localdumps -->|"not recommended for"| hang_detection
procdump -.->|"implements"| postmortem_debugger
wer_localdumps -->|"should come before"| postmortem_debugger
crash_dump -.->|"requires"| pdb
crash_dump -->|"verified by"| windbg
minidumpwritedump -->|"recommended for"| custom_diagnostic_report
notmyfault -->|"not recommended for"| wer_localdumps
In the diagram a solid line marks a relation that always holds and a dashed line marks a conditional one (the conditions are given per relation on the detail page). The full list of relations (21 in total, with evidence and certainty) and the definitions of the main concepts are collected on the knowledge map detail page (in Japanese). Data: JSON-LD / Turtle
2. What a Crash Dump Tells You
A crash dump is a snapshot of a single moment. It is less like a security camera and more like a still photo of an accident scene.
That makes this kind of information quite easy to get.
- Which exception code the crash occurred with
- Which thread crashed
- The call stack at that point
- The modules that were loaded
- Depending on how much memory was included, the state of the heap and the contents of objects
On the other hand, some things tend to be missing from a dump alone.
- The sequence of events leading up to the crash
- A growth trend starting hours earlier
- External state involving communication links or equipment
- The most recent input and the business context
So in practice, the basic approach is to combine the dump with logs and heartbeats rather than trying to finish the job with the dump alone.
flowchart TB
accTitle: Combining dumps with logs
accDescr: Diagram showing that a crash dump is strong on the state at a single moment like a still photo of an accident scene, while logs and heartbeats fill in the sequence of events leading up to it and the external state, so the basic approach is to use both together.
d1["Crash dump - a still photo of one moment"] --> mix["Investigate with both combined"]
d2["Logs and heartbeats - the timeline"] --> mix
d1 -.-> s1["Strong on exception codes and stacks"]
d2 -.-> s2["Strong on how things got there"]
Figure 2: The still photo of a dump and the timeline of a log divide the work cleanly between them.
3. The Big Picture of Collection Methods
For dump collection on Windows applications, there are four methods you want to know at the introductory stage.
| Method | Best suited for | Strengths | Caveats |
|---|---|---|---|
| WER LocalDumps | Always-on crash collection as the baseline | Built into Windows. Easy to configure per application | Primarily crash-oriented. Weak for hangs and fine-grained trigger conditions |
| ProcDump | Investigations with a low reproduction rate, hangs, first chance exceptions | Many triggers. Easy to deploy in the field | You are now operating an external tool |
| Creating a dump from Task Manager | Manually capturing the current state | Captured on the spot via the GUI | Not automatic collection |
MiniDumpWriteDump |
Building your own diagnostic feature | Easy to bundle attached logs and custom metadata | A sloppy implementation can itself break things |
For beginners, the most important thing is this: before deciding what to capture with, decide under what conditions, to where, and at what size.
flowchart TB
accTitle: What to decide before choosing a tool
accDescr: Diagram showing that in crash dump collection it matters to first decide under what conditions, to where, and at what size to capture, and only then move on to choosing the tool to capture with.
c1["Under what conditions to capture"] --> firstq["Three things to decide first"]
c2["Where to write the output"] --> firstq
c3["At what size to capture"] --> firstq
firstq --> tool["Then choose the tool"]
Figure 3: Decide the conditions, the output location, and the size, and choosing a tool stops being a dilemma.
4. The Recommended First Step Is WER LocalDumps
4.1 The Registry Values to Look at First
Windows Error Reporting (WER) has LocalDumps, which saves user-mode dumps locally after a crash. Since you do not have to distribute any extra tools, it is a very approachable first move.
The base key is here.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
You can put a global configuration here, but in practice it is easier to work with a per-application subkey.
flowchart TB
accTitle: Where to put the LocalDumps configuration
accDescr: Diagram showing that although a global configuration can be placed directly under the LocalDumps key, in practice it is easier to work with a per-application subkey such as MyApp.exe.
key1["LocalDumps key"] --> g1["Global settings directly under it"]
key1 --> a1["Per-application subkey"]
a1 -.-> a2["Easier to work with in practice"]
Figure 4: The same key, but scoping it to a subkey named after the application narrows the blast radius.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe
There are three values to look at first.
| Value | Meaning | Recommended starting point |
|---|---|---|
DumpFolder |
Where dumps are written | Create a dedicated folder |
DumpCount |
Retention count | Start around 5-10 |
DumpType |
0=custom, 1=mini, 2=full | Start with 2; if disk space is tight, use 1 |
4.2 An Example of Per-Application Configuration
For example, if you want to keep up to 10 full dumps for MyApp.exe in C:\CrashDumps\MyApp, you can start with the following.
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpFolder /t REG_EXPAND_SZ /d "C:\CrashDumps\MyApp" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpCount /t REG_DWORD /d 10 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 2 /f
This example has four key points.
- It is scoped to
MyApp.exe, not global - The output is separated into a dedicated folder
- It starts with full dumps
- The retention count is capped at 10
4.3 Verifying That a Dump Was Captured
Once the configuration is in place, it is safer to go through a full capture at least once in a test environment rather than waiting for a crash to occur naturally in production.
There are four things to check.
- Does a
.dmpfile appear in the expected folder? - Is the size in line with operational expectations?
- Can it be opened in WinDbg?
- Is the crash visible in the Application log in Event Viewer?
flowchart TB
accTitle: The verification flow after configuring
accDescr: Diagram showing the flow of going through one full capture in a test environment before waiting for a natural crash in production, checking that a dump appears in the folder, that the size matches expectations, that WinDbg can open it, and that the crash is visible in Event Viewer.
v1["Apply the configuration"] --> v2["Crash it on purpose in a test environment"]
v2 --> v3["Check that a dump appeared and its size"]
v3 --> v4["Check that WinDbg can open it"]
v4 --> v5["Check the Event Viewer log"]
Figure 5: Go through one full capture in a test environment before waiting for a natural crash in production.
4.4 Minimal Code for Crashing on Purpose
Being told to “go through a full capture” is one thing, but waiting for a real crash is no way to verify anything. It is much faster to keep a small EXE whose only job is to crash on purpose around for testing.
For .NET, a console app that just throws an unhandled exception is enough. A managed unhandled exception in .NET terminates the process, so it becomes a WER target as-is.
// CrashTest.csproj: <TargetFramework>net8.0</TargetFramework>
using System;
using System.Threading;
internal static class Program
{
private static void Main()
{
Console.WriteLine($"PID={Environment.ProcessId} / crashing in 3 seconds.");
Thread.Sleep(3000);
throw new InvalidOperationException("intentional crash for dump collection test");
}
}
If you want to verify the native side, causing an access violation (0xC0000005) is closer to the real thing. Mark it volatile so the optimizer does not remove it.
// crash_test.cpp / C++17 / MSVC
int main()
{
volatile int* p = nullptr;
*p = 1; // STATUS_ACCESS_VIOLATION occurs here
return 0;
}
There is one thing here that is easy to get wrong.
The name of the LocalDumps subkey has to match the file name of the EXE you are actually crashing. If you only create a key for MyApp.exe and then crash CrashTest.exe, no dump appears, of course. When testing, either create a temporary key for CrashTest.exe or try it on the global settings instead.
flowchart TB
accTitle: The trap of matching the subkey name
accDescr: Diagram showing that no dump appears unless the LocalDumps subkey name matches the file name of the EXE being crashed, so when testing you either create a temporary key for CrashTest.exe or try it on the global settings.
t1["Create a key only for MyApp.exe"] --> t2["Crash CrashTest.exe"]
t2 --> t3["No dump appears"]
t3 -.-> t4["Match the key name to the EXE you crash"]
Figure 6: A mismatch between the subkey name and the EXE name is the classic reason a verification run produces nothing.
Sysinternals NotMyFault often comes up as a tool for “crashing on purpose,” but it is meant to crash or hang the Windows system itself and produce a blue-screen dump, and it requires administrator rights. For verifying LocalDumps on a user-mode application, a small EXE of your own like the ones above is safer and more reliable.
5. When to Use ProcDump
WER is often enough, but there are situations where ProcDump comes in handy.
- You want to avoid a permanent registry setting
- You want to monitor only a process that is already running
- You want to monitor starting only from the next launch
- You want to see first chance exceptions
- You want to capture a hang
- You want to capture based on performance counters or other conditions
5.1 Frequently Used Options
Narrowing things down to what you actually use at the introductory stage, knowing the following ProcDump options will take you a long way.
| Option | Meaning |
|---|---|
-ma |
Full dump |
-mp |
MiniPlus dump |
-mc <Mask> |
Custom dump. Specify a MINIDUMP_TYPE bitmask in hexadecimal |
-e |
Dump on unhandled exception |
-e 1 |
Dump on first chance / second chance exceptions |
-h |
Dump when a window hangs |
-w |
Wait for the target process to launch |
-x |
Launch the target process and monitor it |
-n |
Maximum number of dumps |
-accepteula |
Automatically accept the first-run EULA prompt |
5.2 Representative Command Examples
Full dump of an already-running process on unhandled exception
procdump -accepteula -ma -e 1234 C:\CrashDumps\MyApp
Wait for the next launch, then full dump on unhandled exception
procdump -accepteula -ma -e -w MyApp.exe C:\CrashDumps\MyApp
Launch the process yourself and monitor it directly
procdump -accepteula -ma -e -x C:\CrashDumps\MyApp MyApp.exe
Also capture first chance exceptions
procdump -accepteula -ma -n 3 -e 1 MyApp.exe C:\CrashDumps\MyApp
Capture a hang
procdump -accepteula -h MyApp.exe C:\CrashDumps\MyApp
5.3 Why -i Should Not Be Your First Move
ProcDump can also be registered as a postmortem debugger with -i. This is powerful, but it reaches into machine-wide crash-time behavior, which makes it a little heavy as the very first step at the introductory stage.
So it is easier to start with per-application WER configuration or with ProcDump’s -w / -x / PID targeting.
flowchart TB
accTitle: Why -i should not be your first move
accDescr: Diagram showing that ProcDump -i is a powerful way to register a postmortem debugger but reaches into machine-wide crash-time behavior, so at the introductory stage it is easier to start with per-application WER configuration or with ProcDump -w, -x, or PID targeting.
i1["Register with ProcDump -i"] --> i2["Reaches into machine-wide behavior"]
i2 -.-> i3["Too heavy as a first move for beginners"]
i4["Start with per-application configuration"] --> i5["Per-application WER configuration"]
i4 --> i6["ProcDump -w, -x, or PID targeting"]
Figure 7: Start from an entry point whose blast radius stays within a single application.
6. How to Think About Custom Collection with MiniDumpWriteDump
Custom collection is a good fit in situations like these.
- You want a “Save diagnostic information” button in the UI
- You want to bundle logs, settings, and trace IDs together with the dump
- You want to include related child or helper processes as well
- You want to apply your own masking or compression before uploading
The central API here is MiniDumpWriteDump.
That said, it has some quirks. At the introductory stage, the two points you especially do not want to get wrong are these.
- If at all possible, call it from a process other than the one being dumped
- Treat the DbgHelp family of APIs as single-threaded
flowchart TB
accTitle: Two points not to get wrong in custom collection
accDescr: Diagram showing that in custom collection with MiniDumpWriteDump you should not get two points wrong, namely calling it from a process other than the one being dumped and treating the DbgHelp family as single-threaded.
md1["Custom collection with MiniDumpWriteDump"] --> md2["Call it from a separate process"]
md1 --> md3["DbgHelp assumes single-threaded use"]
md2 -.-> md4["A sloppy implementation breaks things instead"]
md3 -.-> md4
Figure 8: The quirks of custom collection come down to two things: where you call it from, and threading.
7. Choosing Between Minidumps, Full Dumps, and In-Between Sizes
A lot of people get stuck here. Here is how we choose in practice, in table form.
| Type | Best suited for | Pros | Caveats |
|---|---|---|---|
| Minidump | Rolling out broadly first, keeping sharing lightweight | Small, easy to transfer | Limited depth of state reconstruction |
| Full dump | Prioritizing root-cause investigation, suspecting native boundaries or the heap | The most information captured | Large size, higher risk of including confidential data |
| MiniPlus / Custom | When mini is not enough and full is too heavy | Strikes a balance | Requires tuning knowledge |
The recommendation for beginners is quite simple.
- Full dumps on dev / test machines
- In customer environments, choose mini or full based on operational constraints
- If you suspect memory corruption, native DLLs, COM, P/Invoke, or state anomalies after long-running operation, lean toward full
flowchart TB
accTitle: A first pass at choosing the dump type
accDescr: Diagram showing the approach of using full dumps on dev and test machines, choosing mini or full in customer environments based on operational constraints, and leaning toward full when memory corruption, native boundaries, or state anomalies after long-running operation are suspected.
e1{"Which environment are you capturing in"}
e1 -->|"Dev / test machine"| f1["Full dump"]
e1 -->|"Customer environment"| f2["Mini or full based on operational constraints"]
f2 -.->|"Signs of corruption or native boundaries"| f1
Figure 9: When in doubt, let the environment decide, and the stronger the suspicion, the further you lean toward full.
7.1 How Do You Actually Specify MiniPlus / Custom?
The third row of the table is the one where the way to specify it is a little unclear, so here is some added detail.
With WER LocalDumps, you set DumpType to 0 (custom) and then put a combination of MINIDUMP_TYPE bits into CustomDumpFlags. CustomDumpFlags is only used when DumpType=0, and its default is 0x00000121 (the combination of MiniDumpWithDataSegs, MiniDumpWithUnloadedModules, and MiniDumpWithProcessThreadData).
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v CustomDumpFlags /t REG_DWORD /d 0x121 /f
With ProcDump, -mp is MiniPlus and -mc <Mask> is custom.
procdump -accepteula -mp -e MyApp.exe C:\CrashDumps\MyApp
Despite the name, the contents of a MiniPlus dump are quite close to a full dump. According to the documentation, it includes all private memory plus all read/write image and mapped memory, and then holds the size down by excluding only the single largest private region above 512 MB. The result sits in the position of “as detailed as a full dump, but 10% to 75% of the size.”
There are two caveats, though.
- Because of debugging constraints, CLR processes are captured as full (
-ma) even when you specify-mp. Counting on MiniPlus to shrink the size of a .NET application usually does not pan out - If your motivation for keeping the size down is to reduce the amount of confidential data pulled in, it is more straightforward to think in terms of minidumps rather than MiniPlus
flowchart TB
accTitle: Where MiniPlus sits and its constraints
accDescr: Diagram showing that MiniPlus includes all private memory plus read/write image and mapped memory and excludes only the single largest private region above 512 MB, landing at 10 to 75 percent of a full dump, but that CLR processes are captured as full even when -mp is specified.
mp1["Capture with MiniPlus"] --> mp2["Includes almost all private memory"]
mp2 --> mp3["Excludes only the huge private region"]
mp3 --> mp4["Smaller than full, still detailed"]
mp1 -.->|"For CLR processes"| mp5["Captured as a full dump"]
Figure 10: MiniPlus is close to a full dump in content, and it does not shrink anything for .NET applications.
8. What to Decide Up Front Operationally
Dump collection trips up far more often on operations than on implementation. Here is what you want to decide in advance.
8.1 How to Retain PDBs and Binaries
This is the single most important thing.
- The exact version of the shipped EXE / DLL
- The PDBs corresponding to that version
- Which commit and which build pipeline produced it
- Version information for the installer and distributed artifacts
8.2 Where to Write Dumps, and How Many to Keep
Full dumps get quite large. It is safer to decide the output location and retention policy from the start.
- Do not leave dumps sitting directly on the system drive
- Separate them into a dedicated folder
- Cap the count with
DumpCountor-n - Separate long-term storage from initial intake
8.3 Who Is Allowed to Look
Full dumps may contain confidential or personal information.
- Plaintext configuration
- Connection strings
- Tokens and credentials
- Business data that was being handled just before the crash
- File paths and user names
So along with designing how to capture, you also need to decide who is allowed to touch the dumps.
flowchart TB
accTitle: Three things to decide up front operationally
accDescr: Diagram showing that because crash dump collection trips up more often on operations than on implementation, you should decide up front how to retain PDBs and binaries, where to write dumps and how many to keep, and who is allowed to look at them.
op1["Retaining PDBs and binaries"] --> op4["Decide these up front"]
op2["Output location and retention count"] --> op4
op3["Who is allowed to look"] --> op4
op4 -.-> op5["Operations trip you up more often than implementation"]
Figure 11: Failures in dump collection usually come from decisions that were never made on the operational side.
9. The Shortest Path to Analysis Once You Have a Dump
After capturing a dump, the first steps are surprisingly plain.
9.1 Install WinDbg
Today’s WinDbg is easy to install from the Microsoft Store or via winget.
winget install Microsoft.WinDbg
9.2 Open the Dump
windbg -z C:\CrashDumps\MyApp\MyApp_YYMMDD_HHMMSS.dmp
The file name here is the default name ProcDump assigns. ProcDump’s default file name is PROCESSNAME_YYMMDD_HHMMSS.dmp, and you can use PROCESSNAME, PID, EXCEPTIONCODE, YYMMDD, and HHMMSS as substitution specifiers.
WER LocalDumps, on the other hand, creates files with a different naming scheme from ProcDump. The naming rule is not documented on Microsoft Learn, so instead of guessing the name and searching for it, it is more reliable to list the output folder sorted by modification time.
dir /o-d "C:\CrashDumps\MyApp\*.dmp"
If you have not set DumpFolder, the default output location is %LOCALAPPDATA%\CrashDumps. Note, however, that a service crash goes to the profile folder of the account it runs as. For a System service that is %WINDIR%\System32\Config\SystemProfile, and for Network Service / Local Service it is under %WINDIR%\ServiceProfiles. When you think no dump was produced, this is the first place to suspect.
flowchart TB
accTitle: Where to look when the dump is nowhere to be found
accDescr: Diagram showing that when DumpFolder is not set the default is CrashDumps under LOCALAPPDATA, while a service crash goes to the profile folder of the account it runs as, so that is the first place to suspect when no dump appears.
fq1["The dump is nowhere to be found"] --> fq2{"How was it running"}
fq2 -->|"Normal application"| fp1["CrashDumps under LOCALAPPDATA"]
fq2 -->|"Service"| fp2["Under the profile of the run-as account"]
fp2 -.-> fp3["SystemProfile or ServiceProfiles"]
Figure 12: The default output location differs per account, so start by questioning where you are looking.
9.3 Set Up Symbols
First get Microsoft’s public symbols working, then add the location of your own PDBs.
.symfix C:\Symbols\Microsoft
.sympath+ C:\Symbols\MyApp
.reload
9.4 Start with the Automated Analysis
!analyze -v
From there, check in order:
- Which exception code it is
- What the faulting module is
- How far your own code is visible on the stack
- Whether there are suspicious waits or blockages on threads other than the exception thread
flowchart TB
accTitle: The shortest analysis path once you have a dump
accDescr: Diagram showing the flow of installing WinDbg, opening the dump, setting up Microsoft public symbols and your own PDBs, starting with the automated analyze -v output, and then reading the exception code, the faulting module, how far your own code is visible, and blockages on other threads in order.
an1["Install WinDbg"] --> an2["Open the dump"]
an2 --> an3["Set up symbols and PDBs"]
an3 --> an4["Start with the automated analysis"]
an4 --> an5["Read the exception code and stack in order"]
Figure 13: Open it, get symbols resolving, and start reading from the automated analysis - that is the shortest path.
10. Common Pitfalls
10.1 You Got the Dump, but There Are No PDBs
This one is extremely common. The dump collection itself succeeded, but you are short on material to read it with. Put the PDB retention design in place at the same time as the collection setup.
10.2 Not Checking the ACL on DumpFolder
With services or privilege-separated processes, this is an easy place to end up with nothing. Verify first that the process can actually write there. Microsoft Learn says the same thing: if you use a path other than the default, confirm that the ACL allows the crashing process to write to it.
You can view the current ACL with icacls.
icacls C:\CrashDumps\MyApp
If write permission is missing, grant M (modify) to the account the process runs as. A dump folder needs the same permission on the files beneath it, so add (OI) and (CI) to make it inherit.
rem Example: a service running as Network Service
icacls C:\CrashDumps\MyApp /grant "NT AUTHORITY\NETWORK SERVICE:(OI)(CI)M"
(OI) makes the ACE inherit to files beneath the folder, and (CI) to folders beneath it. The scope of that inheritance is exactly who can read the dumps, so before you apply it, check once that it does not conflict with the policy you decided in 8.3.
flowchart TB
accTitle: The flow for checking the ACL on DumpFolder
accDescr: Diagram showing the flow of checking the current ACL with icacls because services and privilege-separated processes often fail to write, granting modify permission with inheritance to the run-as account if it is missing, and reconciling that inheritance scope with the access policy.
ac1["Check the current ACL with icacls"] --> ac2{"Can the run-as account write"}
ac2 -->|"Cannot write"| ac3["Grant modify permission with inheritance"]
ac2 -->|"Can write"| ac4["Leave it as is"]
ac3 -.-> ac5["Reconcile the inheritance scope with the access policy"]
Figure 14: Checking whether it can write and checking who can read are done in the same place.
10.3 Continuously Writing Full Dumps to the System Drive on a Production Machine
This is the classic way to fill a disk. Put retention limits and output-folder separation in from the start.
10.4 Trying to Cover Hangs Entirely with WER Alone
WER LocalDumps is strong primarily for crashes. For hangs and first chance exceptions, ProcDump is often the better fit.
10.5 Leaving -e 1 On Permanently and Drowning in Exceptions
First chance exceptions are useful, but there are simply a lot of them. Realistically: cap the count, enable it only for short periods, and limit the target.
11. Summary
Crash dumps are a remarkably strong observation point for failures with low reproduction rates. Especially when a Windows application involves COM, P/Invoke, native DLLs, or long-running operation, it is worth deciding from the start what will be left behind when it crashes.
The recommended order is simple.
- First, set up WER LocalDumps per application
- Add ProcDump if needed
- If you want even more control, use
MiniDumpWriteDumpfrom a separate process
Proceed in this order and you are unlikely to go far wrong.
12. References
- Collecting User-Mode Dumps - Win32 apps | Microsoft Learn
- ProcDump v11.1 - Sysinternals | Microsoft Learn
- MiniDumpWriteDump function (minidumpapiset.h) - Win32 | Microsoft Learn
- User-mode dump files - Windows drivers | Microsoft Learn
- Analyzing a User-Mode Dump File - Windows drivers | Microsoft Learn
- Install the Windows debugger - Windows drivers | Microsoft Learn
- Symbol path for Windows debuggers - Windows drivers | Microsoft Learn
- !analyze (WinDbg) - Windows drivers | Microsoft Learn
- Troubleshoot processes by using Task Manager - Windows Server | Microsoft Learn
- Enabling Postmortem Debugging - Windows drivers | Microsoft Learn
- MINIDUMP_TYPE enumeration (minidumpapiset.h) - Win32 | Microsoft Learn
- icacls - Windows commands | Microsoft Learn
- NotMyFault - Sysinternals | Microsoft Learn
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
Designing Windows Apps to Leave Logs and Dumps When They Crash
How to combine regular logging, a final crash marker, WER LocalDumps, and a watchdog process so that even when a Windows app dies from an...
Reading Crash Dumps with WinDbg + SOS — A Practical Guide to Analysis After Collection
Explains how to actually read a collected Windows crash dump using WinDbg and the SOS extension. Covers symbol path configuration, tracki...
Incident Response Doesn't End at Recovery — A Postmortem (Recurrence Prevention) Template for Small Development Teams
Treating an incident as over once it's fixed and apologized for guarantees you'll repeat it. This article translates the blameless postmo...
Sleep, Hibernation, Modern Standby, and Long-Running Apps — Designing Around 'It Stopped Overnight'
Why a long-running Windows app can end up 'stopped by the time you check it in the morning,' worked through from the differences between ...
When You Inherit a System With No Source Code and No Documentation — A Practical Playbook for Keeping It Running
A practical playbook for starting operations and maintenance on a business system that has no source code and no specifications. Covers p...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Bug Investigation & Long-Run Failures
Topic page for intermittent failures, communication diagnosis, long-run crashes, and failure-path test foundations.
Where This Topic Connects
This article connects naturally to the following service pages.
Bug Investigation & Root Cause Analysis
Narrowing down a problem by combining crash dumps, logs, and reproduction conditions is a natural fit for our bug investigation and root-cause analysis service. For crashes that only occur on site, or failures after long-running operation, designing the observation strategy itself becomes critical.
Technical Consulting & Design Review
If you want to sort out what to collect in production, how to weave dumps and logs into your design, and even permissions and retention policies, this works well as a technical consulting or design review engagement.
Frequently Asked Questions
Common questions about the topic of this article.
- What is a crash dump? What can it tell me?
- It is a file holding the state of a process at the moment it crashed, a snapshot rather like a still photo of an accident scene. After the fact you can check the exception code, the thread that crashed and its call stack, the modules that were loaded, and, depending on how much memory you included, even the contents of objects on the heap. What it tends to lack is the sequence of events that led up to the crash and the external state of communication links or equipment, so in practice you use it together with logs and heartbeats.
- Where do I configure WER LocalDumps?
- You configure it in the registry under HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps. In practice it is easier to work with a per-application subkey such as MyApp.exe than with the global settings. The first three values to look at are DumpFolder for the output location, DumpCount for the retention count, and DumpType for the kind of dump. With those in place, you get a dump saved locally after a crash without distributing any extra tools.
- Should I choose minidumps or full dumps?
- As a rule of thumb, use full dumps (DumpType=2) on dev and test machines, and in customer environments choose either a minidump (DumpType=1) or a full dump depending on disk space and confidentiality requirements. Lean toward full dumps if you suspect memory corruption, native DLLs, COM, P/Invoke, or state anomalies after long-running operation. Full dumps are large, though, and carry the risk of pulling in confidential data such as connection strings and tokens, so decide the storage location, retention count, and access rights up front.
- When should I use ProcDump?
- WER LocalDumps is fundamentally crash-oriented, so ProcDump is the better fit when you also want to see hangs or first chance exceptions, when you want to avoid a permanent registry setting, or when you want to monitor only a process that is already running. The representative options are -ma for a full dump, -e to capture on an unhandled exception, -h to detect a hang, and -w to wait for a launch. Because -e 1, which targets first chance exceptions, tends to produce a lot of hits, the realistic approach is to use it briefly and narrowly, for example by capping the count with -n.