A Practical Guide to Process Monitor (ProcMon) — Pinpointing "Settings Not Applied" and "ACCESS DENIED" in 10 Minutes
· Go Komura · Process Monitor, Sysinternals, Bug Investigation, Debugging, Troubleshooting, Windows Development, Operations, Technical Consulting
“I edited the config file, but the app’s behavior hasn’t changed.” “It works on my dev machine, but crashes right after launch only on the customer’s machine.” “It worked yesterday. I haven’t changed a single line of code.” — Bug investigation requests usually arrive in one of these shapes. And for many symptoms of this kind, no amount of reading the source code will get you to the root cause, because which files the app actually reads, which registry keys it looks at, and what fails is determined by the runtime environment, not the code.
The tool that records “what actually happened” is Process Monitor (ProcMon), one of the Sysinternals tools Microsoft provides free of charge. It’s essentially a behavior log recorder for Windows that records file system, registry, and process/thread activity in real time — and along with WinDbg, it’s one of the tools we reach for most often in our own bug investigations.1
As powerful as it is, if you just launch it and do nothing else, thousands to tens of thousands of events per second start streaming past, and first-time users tend to conclude “there’s too much to read.” This article organizes the fastest practical route to using ProcMon in the field — how to apply filters, how to read the Result column, standard investigation patterns by symptom, cautions for production environments, and how to divide work with other investigation tools — from the perspective of real-world bug investigation.
1. The Bottom Line First
- The question ProcMon answers is: “When did this process do what, on which path, and with what outcome?” Within a few minutes you can find out where a config file is actually being read from, in what order DLLs were searched for, and which operation ended in ACCESS DENIED.
- The standard usage pattern is: “first apply an Include on Process Name for the target process, then narrow further by Result to focus on failures.” It’s not a tool meant to be read line by line from the top.
- The Result column contains many values that look abnormal but are actually normal. BUFFER OVERFLOW is a normal API round trip, and NAME NOT FOUND is usually just an intermediate step in a search order (Section 4).
- A filter is only a display-level narrowing — behind the scenes, all events are still being recorded. When saving a log to hand off to someone, save all events. Conversely, for long captures, use Drop Filtered Events to protect memory (Section 5).
- ProcMon isn’t a cure-all. “Which process currently has this file open” is Process Explorer’s job; the state at the moment of a crash belongs to a crash dump; and where CPU time is being spent belongs to PerfView (Section 7).
Here’s a quick-reference table for choosing a tool based on the symptom.
| Symptom / what you want to know | Tool to reach for first |
|---|---|
| Settings aren’t applied / which file or registry key is being read | ProcMon |
| App won’t start only in a specific environment / DLL not found | ProcMon |
| Identifying ACCESS DENIED or permission-related failures | ProcMon |
| Can’t delete a file — who’s holding onto it | Process Explorer (handle search) |
| App crashes — cause of an exception/crash | Crash dump + WinDbg |
| App is slow — where CPU/memory is being spent | PerfView / dotnet-trace |
| Handles or memory keep growing over long-term operation | Process Explorer + handle leak investigation |
| Want to see the contents of network traffic (packets) | Wireshark / pktmon |
2. What ProcMon Is — Setup Takes One Minute
Process Monitor is one of the Sysinternals tools — a monitoring tool that displays file system, registry, and process/thread activity in real time. It’s the successor that merges and enhances two earlier tools, Filemon and Regmon, and it offers per-event detail information, non-destructive filtering, thread stack recording, and boot-time logging.1
Setup is simple. There’s no installer — you just download the ZIP from the download page, extract it, and run Procmon.exe. For an urgent investigation, you can also run it directly from https://live.sysinternals.com/procmon.exe using the Sysinternals Live service.2 On first launch you’re prompted to accept the license agreement, and because it loads a kernel driver, administrator privileges (UAC elevation) are required. The general question of when administrator privileges are needed in Windows is covered in “When Does Windows Actually Require Administrator Privileges?” — tools that observe system-wide events are a textbook case of “elevation required.”
Capture begins the moment you launch it, and events immediately start streaming across the screen. You only need to remember three main operations.
| Operation | Shortcut | Meaning |
|---|---|---|
| Start/stop capture | Ctrl+E | Toggles recording on/off. The basic pattern is start right before the reproduction steps, stop right after |
| Clear the display | Ctrl+X | Resets what’s shown. Pressing this right before the reproduction steps reduces noise |
| Filter dialog | Ctrl+L | Add/edit narrowing conditions (Section 3) |
Each event line consists of Time, Process Name, PID, Operation, Path (the target path), Result, and Detail. Operation is at roughly the granularity of Win32 APIs, such as CreateFile (opening/creating a file), ReadFile/WriteFile, and RegOpenKey/RegQueryValue. In other words, ProcMon’s log is a record of the conversation between the app and the OS — it directly exposes the gap between what an app intends to do when reading a config file, and what it actually reads.
3. Filters — ProcMon Is a Tool You Narrow Down Before Reading
If you capture without doing anything else, even an idle Windows machine produces thousands of events per second. It’s fair to say ProcMon’s practical value comes down to how you use filters, and the standard approach is a two-stage process:
Stage 1: Narrow by process. Open the filter dialog with Ctrl+L and add Process Name / is / myapp.exe / Include. You can also drag the crosshair icon in the toolbar onto the target app’s window to filter to that process alone.
Stage 2: Narrow by result or operation. If you want to find failing operations, use Result / is not / SUCCESS / Include (to show only failure cases). If you only want to see writes, use Category / is / Write / Include. If you want to know who is touching a particular config file, skip the process filter and use Path / contains / app.config / Include, and so on.
Another technique used heavily in practice is interactive narrowing by right-clicking event rows. Once you find one line close to what you’re looking for, right-click it and choose “Include ‘this path’” or “Exclude ‘this process’” — filters stack up without ever opening the dialog. The standard workflow is to Exclude noise sources (antivirus software, indexers, etc.) one by one, leaving only the operations immediately before and after the one you care about. Highlighting (Ctrl+H) is also useful as a visual aid — you can color rows using the same kind of condition expressions as a filter, so when you want to see the overall flow but still make failure cases stand out, use highlighting instead of filtering.
There are three behaviors that will trip you up if you don’t know about them in advance.
- A filter narrows the display, not the recording. Behind the scenes (by default), all events are still being recorded, and you can return to the full picture at any time by removing the filter. This is why it’s called a non-destructive filter — it’s designed so you’re unlikely to “over-filter and miss evidence.”1
- Filter settings carry over the next time you launch ProcMon. Everyone runs into this at least once: a filter from a previous investigation is still applied, and you end up puzzled that “nothing is showing up.” If the display looks wrong, the first thing to try is Reset Filter (Ctrl+R) from the Filter menu.
- Several Excludes are applied by default. ProcMon itself, paging I/O, and so on are excluded from the start. If your investigation requires “the entire system, with nothing left out,” keep this default filter in mind.
4. Reading the Result Column — Things That Look Abnormal but Are Normal
Once you narrow down to failure cases with a filter, you’ll be surprised to find a huge number of “abnormal-looking” results. The important thing here is that most of the abnormal-looking values in the Result column are part of normal operation. Here’s a summary of how to read the main Result values.
| Result | Meaning | Likelihood of being an actual problem |
|---|---|---|
| SUCCESS | Succeeded | None (though “succeeding somewhere it shouldn’t” can itself be the cause) |
| NAME NOT FOUND | The name doesn’t exist at that path | Low to medium. Usually an intermediate step in a search order. If it never succeeds at all, it’s the culprit |
| PATH NOT FOUND | An intermediate folder itself doesn’t exist | Medium. A classic sign of a typo, a folder that was never created, or an environment difference |
| ACCESS DENIED | Access denied | High. Permissions, ACLs, antivirus software, writes to a protected area |
| SHARING VIOLATION | Sharing violation (another process has it open exclusively) | High. A file lock conflict — proceed to identify the other process |
| BUFFER OVERFLOW | The buffer was too small, so the required size was returned | None. A normal API round trip (see FAQ) |
| REPARSE | Followed a reparse point (symbolic link, etc.) | Almost none. Read it as a trace of a path being redirected |
| NO MORE FILES / NO SUCH FILE | The end of an enumeration, etc. | Almost none |
Of these, the three that take center stage in an investigation are NAME NOT FOUND, ACCESS DENIED, and SHARING VIOLATION. Each has its own standard investigation pattern, which we’ll cover by symptom in the next section.
Conversely, one pattern that’s easy to overlook is “SUCCESS being the root cause.” For example, more than once the answer to “the config file I fixed isn’t being applied” turned out to be a SUCCESS on an old config file located somewhere else. If you only look at failure cases, you’ll miss this “wrong right answer” that loaded successfully — so the reliable approach is to narrow by path and look at every access to that file type, including successes.
5. Standard Investigation Patterns by Symptom
5.1 “I fixed the setting, but it’s not being applied” — Identify Where It’s Actually Being Read From
Apply an Include with Path / contains / <config file name> and launch the app, and you get a full list of which folders, and in what order, the app searched for a file with that name. The truth is usually one of the following:
- It was reading a copy under
%APPDATA%orProgramData, not the folder next to the exe (the design copies the file there on first launch) - Registry/system folder access from a 32-bit process was redirected by WOW64, so what you thought you were looking at and what was actually accessed had diverged
- Writes to
Program Filesunder the install location were virtualized (VirtualStore), so reads and writes were silently redirected elsewhere
ProcMon makes any of these obvious at a glance, because the full path appears in Path. For the flip side of this — how config file locations should be designed in the first place — see “More Than Just appsettings.json — Practical Configuration Management.”
5.2 “It Won’t Start Only in This Environment” — Trace the DLL Search
If the app crashes right after launch, or you get a “DLL not found”-style error, Include the process and add Path / ends with / .dll, then watch the chain of NAME NOT FOUND entries. Because Windows DLL search follows a fixed folder order, ProcMon’s log directly shows the pattern: a series of NAME NOT FOUND entries in search order, followed by a SUCCESS somewhere (or never succeeding at all). The DLL that never succeeds is the culprit. Conversely, you can also find the pattern here of “it succeeds, but it’s grabbing an old DLL from an unintended location.” For the reasoning behind the search order, see “How Windows DLL Name Resolution Works.”
A “class not registered” error involving COM/ActiveX takes the same shape, observable as a NAME NOT FOUND under the CLSID key via RegOpenKey. Mix-ups between 32-bit and 64-bit that end up looking at the wrong registry view are exactly the kind of case where ProcMon is the fastest route, following the same procedure described in “Why ActiveX Doesn’t Work in Office 2024/Microsoft 365, and How to Check It.”
5.3 “I’m Getting ACCESS DENIED” — Suspect Whose Privileges It’s Running Under
When you find an ACCESS DENIED, double-click that event and check the Process tab. It shows which user the process was running as, which reveals mismatches like “the service was running as a restricted service account rather than SYSTEM” or “it was running as a different user only when launched via Task Scheduler.” If the target is a file, cross-referencing that path’s ACL will confirm the cause. Note that in cases where antivirus software is interfering, you’ll often see another process (the antivirus engine) touching the same path immediately before or after — this too is evidence unique to a tool like ProcMon that records a full timeline.
5.4 “File Processing Occasionally Fails” — Find the Other Party in a SHARING VIOLATION
A sharing violation is an investigation where timeline is everything. Include by path without filtering by process, and capture — the moment of failure will show who else had the same file open in the surrounding lines. Backup software, antivirus software, and leftover Excel processes are the usual suspects. For a design that avoids this kind of contention in file integration altogether, see “The Basics of Exclusive Control in File Integration,” and for the problem of leftover Excel processes, see “The Problem of EXCEL.EXE Remaining After C# Excel Automation.” It’s worth adding that if all you want to know is “who has this open right now,” Process Explorer’s handle search (Ctrl+F) is faster than ProcMon.3
5.5 “Startup Is Slow” — Get a Rough Sense of Where Time Is Being Spent
Adding the Duration column shows how long each individual operation took. You can also use Process Activity Summary and File Summary from the Tools menu to aggregate operation counts and time per process or per file. This is more than enough to get a rough sense of things like “it was doing tens of thousands of registry reads at startup” or “access to a path over the network was waiting until it timed out.” That said, serious profiling of where CPU time is being spent is not ProcMon’s job. When the slowness is computational rather than I/O-bound, hand off to PerfView and dotnet-trace.
5.6 Startup/Logon-Time Problems — Boot Logging
For cases like “the service fails before logon” or “an app registered to start up doesn’t launch,” where the problem happens before you’d have a chance to launch ProcMon by hand, use Enable Boot Logging from the Options menu. Events from the very start of the next boot are recorded, and the next time you launch ProcMon after that, you’re prompted to save them. Boot-time logging is provided as an official ProcMon feature,1 and for investigations involving startup order or logon scripts, it’s the only window you have into what happened.
6. Saving and Handing Off Logs — When the Customer Has to Capture It
In real-world bug investigation, it’s not unusual that the only environment where the problem reproduces is on the customer’s side. ProcMon logs can be saved as PML files, and opening them on a different machine shows every column and every detail, which makes a division of labor possible: “have the customer capture it, and we’ll analyze it.” Here’s the procedure we use when asking a customer to do this:
- Run Procmon.exe as an administrator and accept the license agreement.
- Once it launches, stop capture with Ctrl+E and clear the display with Ctrl+X.
- Start capture with Ctrl+E and reproduce the problem.
- As soon as it reproduces (or an error appears), stop immediately with Ctrl+E.
- Go to File > Save, and choose All events rather than Events displayed using current filter, save in PML format, ZIP it, and send it over.
The key point is “All events” in step 5. Even if a filter is still applied on their screen, the full recording is intact, so we’re free to re-narrow it however we like on our end. For problems that take time to reproduce, or where you don’t know when they’ll occur, capturing as-is will keep consuming memory, so specify at least one of the following: enable Filter > Drop Filtered Events to record only the target process, or switch the recording destination from virtual memory to a file via File > Backing Files. Run it overnight without knowing either of these two options, and ProcMon will exhaust memory before the problem under investigation ever occurs.
If you want to automate this, command-line switches are also available. /AcceptEula suppresses the license agreement dialog, /BackingFile specifies the recording destination file, /Runtime specifies an automatic stop after a given number of seconds, and /Terminate shuts down a running instance of ProcMon — combining these lets you set things up so that “an operator runs a single batch file when a failure occurs, and evidence is preserved.” The idea of deciding in advance what to collect when a failure occurs is shared with crash dump collection and event log design.
7. ProcMon’s Limits, and How to Divide Work With Other Tools
ProcMon is a tool for viewing a “timeline of operations,” and it isn’t suited to every kind of investigation. Here’s how we divide roles across tools in our own investigations.
| Tool | What it shows | When we reach for it |
|---|---|---|
| Process Monitor | Timeline of file, registry, and process launch activity | Environment-dependent bugs; configuration, DLL, permission, and lock issues |
| Process Explorer | Current state of processes, handles, and DLLs | Tracking down who’s holding a file, observing handle counts3 |
| WinDbg + dumps | Memory and stacks at the moment of a crash or hang | Analyzing exceptions, crashes, and freezes |
| PerfView / dotnet-trace | CPU samples, GC, allocations | Quantitative investigation of “it’s slow” |
| Application Verifier | API misuse, forced failure-path testing | Pre-shipment abnormal-path testing |
| Wireshark / pktmon | Packet contents | Protocol-level network investigation4 |
There are three boundary areas that are easy to get confused about:
- Networking: ProcMon records TCP/UDP connection and send/receive events (which process communicated with where), but it does not show packet contents. For protocol-level investigation, use Wireshark or Windows’ built-in pktmon.4
- Memory: “Memory usage keeps growing” is not something ProcMon can track. For managed heaps, proceed to distinguishing GC behavior from a leak; for handles, proceed to handle leak investigation.
- Stacks: ProcMon actually does record the issuing thread stack for each event (double-click an event → Stack tab), and if you configure symbols, you can identify at the code level exactly who issued a given file access. At this point you’re already stepping into WinDbg territory, and managing symbols (PDBs) starts to matter.
8. Summary — See the Facts Before You Read the Code
The first thing to do when investigating an environment-dependent bug isn’t reading the code or forming a hypothesis — it’s capturing a record of what actually happened. ProcMon is the fastest route to that: one minute to set up, a few minutes to capture, and you have the hard facts of which path was touched, in what order, under what privileges, and what failed. Master these three things — the two-stage filter (process → Result), how to read Result values that look abnormal but aren’t, and handing off logs saved with all events — and an investigation that had stalled at “it doesn’t reproduce on the dev machine” can move forward the same day.
We take on investigations of bugs whose reproduction conditions are unclear, set up evidence-collection procedures for failures that only occur in a customer’s environment, and perform root-cause analysis combining ProcMon, WinDbg, and PerfView. We can help even from the stage where “nothing shows up in the logs, but it still doesn’t work.”
Related Articles
- Reading a Crash Dump with WinDbg + SOS — A Practical Introduction to Post-Collection Analysis
- Identifying “Slow” with PerfView and dotnet-trace — A Practical Introduction to .NET Performance Investigation
- An Introduction to Windows Crash Dump Collection — WER/ProcDump/WinDbg
- How Windows DLL Name Resolution Works — Search Order and SxS
- Investigating a Long-Run Crash in an Industrial Camera Application — Handle Leak Edition
Related Consulting Areas
KomuraSoft LLC handles root-cause investigation for environment-dependent bugs that are hard to reproduce, setting up evidence-collection procedures for failures, and troubleshooting support for existing Windows applications.
- Bug Investigation & Root-Cause Analysis
- Technical Consulting & Design Review
- Maintenance & Modernization of Existing Windows Software
- Contact Us
References
-
Microsoft Learn, Process Monitor - Sysinternals. On Process Monitor being a monitoring tool that displays file system, registry, and process/thread activity in real time; being the successor to Filemon and Regmon; and its features including non-destructive filtering, thread stack recording, and boot-time logging. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Sysinternals Live. On Sysinternals Live being a service that lets you run tools directly via a
live.sysinternals.com/<toolname>URL or file share, without downloading them first. ↩ -
Microsoft Learn, Process Explorer - Sysinternals. On Process Explorer’s ability to display a process’s open handles and loaded DLLs, and its use for searching which process has a specific file or directory open. ↩ ↩2
-
Microsoft Learn, Packet Monitor (Pktmon). An overview of Windows’ built-in packet capture tool, Packet Monitor, and its uses. ↩ ↩2
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
Pinpointing "Slow" with PerfView and dotnet-trace — A Practical Introduction to .NET Performance Investigation
When a business app is "slow," "pegs the CPU," or "occasionally freezes," which tool should you reach for, and what should you look at? T...
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...
When Task Scheduler Tasks Don't Run or Exit with 0x1 — Isolating the Cause and Designing for Reliable Operation
A design guide to putting Windows Task Scheduler into reliable production use: execution accounts and logon types, what 'Run whether user...
When Not to Move a Windows App to the Web: A Decision Table and the Practical Answer of Splitting
Requests to move in-house Windows apps to the web are increasing, but for apps built around device integration, local file processing, of...
Localizing WinForms/WPF Apps — resx, Satellite Assemblies, and Culture Switching in Practice
A practical guide to localizing Windows desktop apps, covering the difference between CurrentCulture and CurrentUICulture, how resx and s...
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 reproduction conditions and identifying root causes for symptoms like "the setting isn't applied" or "it only fails to start on one particular environment" is at the core of bug investigation and root-cause analysis engagements.
Technical Consulting & Design Review
Setting up procedures for introducing investigation tools, and designing operational practices around what evidence to collect when a failure occurs, fall under technical consulting that involves design review.
Frequently Asked Questions
Common questions about the topic of this article.
- Is it safe to run ProcMon in a production environment?
- A short capture is common practice in the field, but it isn't unconditionally safe. ProcMon loads a driver and records a huge volume of events, so on servers with high event volume it will noticeably consume CPU and memory. There are three countermeasures: (1) start immediately before the reproduction steps and stop immediately after, keeping the capture window as short as possible; (2) if long-term monitoring is required, enable Drop Filtered Events from the Filter menu so events outside the filter are not retained; and (3) configure a Backing File so recording goes to a file rather than memory. It's also advisable to run it through the same approval process as any other change — for example outside business hours, or after taking a snapshot.
- There are too many events and I can't find the line I'm looking for. How should I narrow it down?
- The standard approach is to first apply an Include on Process Name to limit events to the target process, and then narrow further by Result to focus on failure cases (NAME NOT FOUND, ACCESS DENIED, and so on). Once you find one line close to what you're after, right-click it and use the Include or Exclude options that appear to narrow down interactively. Conversely, a common mistake is saving the log while a filter is still applied and ending up with insufficient information — when saving the log to a file to hand off to someone else, remember that a filter is only a display-level narrowing, and save all events instead. Also note that filter settings carry over the next time you launch ProcMon, so if "nothing is displayed," check whether an old filter from a previous session is still in place via Reset Filter in the Filter menu.
- Is BUFFER OVERFLOW in the Result column a sign of a bug or an attack?
- No. It has nothing to do with the security term "buffer overflow attack" — it simply means "the data needed was larger than the buffer the caller provided, so the required size was returned," which is a normal API round trip. Many APIs are designed to be called first with a small buffer to learn the required size, then reallocated and called again, so if a SUCCESS on the same path follows immediately afterward, there's no problem. Likewise, NAME NOT FOUND is often just "not found partway through the search order" — if it eventually succeeds somewhere, it isn't abnormal. A failure Result can only be called a root cause once you've confirmed that the failed operation is actually causally connected to the application's symptom.
- How do you decide between Process Explorer and Process Monitor?
- Process Monitor is a tool for recording the flow of operations over time — when, which process, on which path, did what, and with what outcome. Process Explorer is a tool for viewing the current state at this moment — which process has which file or DLL open, and current CPU/memory usage. For example, if you want to know "I can't delete this file — who's holding onto it?", Process Explorer's handle search is the fastest route. If you want to know "in what order, and when, is the application reading this file?", that's Process Monitor. In practice, we keep both on hand as part of the Sysinternals Suite, and remember it as: state → Process Explorer, history → Process Monitor.
Author Profile
Profile page for the article author.
Go Komura
Representative of KomuraSoft LLC
Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.
Public links