Process Monitor(ProcMon)實戰指南 ── 在10分鐘內找出「設定未被讀取」「ACCESS DENIED」的原因

· · Process Monitor, Sysinternals, 缺陷調查, 偵錯, 疑難排解, Windows 開發, 維運, 技術諮詢

「明明已經改寫了設定檔,應用程式的行為卻沒有改變」「開發機上能正常運作,卻只有客戶端的機器一啟動就當掉」「昨天為止都還能運作。程式完全沒有變更過」──不具調查的委託,大多都是以這樣的形式出現。而這類症狀,大多數情況下無論怎麼閱讀原始碼,都無法找到原因。因為應用程式實際讀取了哪個檔案、查看了哪個登錄檔、在哪裡失敗,並不是由程式碼決定,而是由執行環境決定的。

而能夠記錄下「實際發生了什麼」的,就是 Microsoft 免費提供的 Sysinternals 工具 Process Monitor(ProcMon)。它能即時完整記錄檔案系統、登錄檔、處理程序/執行緒的活動,可說是Windows 的行為記錄器,在本公司的不具調查中,也是與 WinDbg 並列、經常派上用場的工具。1

雖然功能強大,但若什麼都不設定就直接啟動,每秒會湧入數千到數萬筆事件,第一次接觸的人往往會覺得「太多了,看不懂」而放棄。本文將從不具調查現場的角度,整理出在實務上使用 ProcMon 的最短路徑──包括 Filter 的設定方式、Result 欄位的判讀方式、依症狀分類的常見調查模式、正式環境中的注意事項,以及與其他調查工具的分工方式。

1. 先說結論

  • ProcMon 能回答的問題是「這個處理程序,何時、對哪個路徑、做了什麼、結果如何」。設定檔究竟是從哪裡被讀取的、DLL 是以什麼順序被搜尋的、哪個操作變成了 ACCESS DENIED,這些幾分鐘內就能查明。
  • 使用上的常規做法是「先用 Process Name 對目標處理程序套用 Include,再用 Result 篩選出異常系」。它不是一款讓你從頭到尾閱讀原始事件的工具。
  • Result 欄位中,有許多看起來異常、實際上正常的內容。BUFFER OVERFLOW 是正常的 API 往返,NAME NOT FOUND 大多只是搜尋順序中的過程(第 4 章)。
  • Filter 只是顯示上的篩選,背後其實全部事件都有被記錄下來。將記錄檔存檔交給他人時,請保存全部事件。反過來說,長時間擷取時,可用 Drop Filtered Events 來保護記憶體(第 5 章)。
  • ProcMon 並非萬能。「現在是哪個處理程序佔用著這個檔案」屬於 Process Explorer 的範疇,當機瞬間的狀態屬於當機傾印(crash dump)的範疇,CPU 用在哪裡則屬於PerfView的範疇(第 7 章)。

以下先提供依症狀選擇工具的速查表。

症狀・想知道的事 首先使用的工具
設定未生效/想知道讀取了哪個檔案或登錄檔 ProcMon
僅在特定環境下無法啟動・找不到 DLL ProcMon
ACCESS DENIED・找出與權限相關的失敗 ProcMon
檔案無法刪除,想知道是誰佔用著 Process Explorer(控制代碼搜尋)
應用程式當機。例外・當機的原因 當機傾印 + WinDbg
速度慢。CPU・記憶體用在哪裡 PerfView / dotnet-trace
長期運作下控制代碼・記憶體持續增加 Process Explorer + 控制代碼洩漏調查
想查看通訊內容(封包) Wireshark / pktmon

2. ProcMon 是什麼 ── 導入只需 1 分鐘

Process Monitor 是 Sysinternals 工具群組之一,是一款即時顯示檔案系統、登錄檔、處理程序/執行緒活動的監控工具。它是整合並強化了過去的 Filemon 與 Regmon 這兩款工具的後繼者,具備逐事件詳細資訊、非破壞性 Filter、執行緒堆疊記錄、開機階段記錄等功能。1

導入方式很簡單。沒有安裝程式,只需從下載頁面取得 ZIP 檔並解壓縮,執行 Procmon.exe 即可。若是緊急調查,也可以利用名為 Sysinternals Live 的服務,直接從 https://live.sysinternals.com/procmon.exe 執行。2 第一次啟動時會要求同意使用授權,且由於需要載入核心驅動程式,因此需要系統管理員權限(UAC 提升)。至於為何需要系統管理員權限這個一般性的問題,在「Windows 何時需要系統管理員特殊權限」中已有說明,能查看整個作業系統事件的工具,正是典型的「需要提升權限」類型。

一啟動,擷取就會開始,畫面上事件也會隨即開始流動。只需要記住三個主要操作即可。

操作 快捷鍵 意義
開始/停止擷取 Ctrl+E 記錄的開/關。基本做法是在重現操作前才開始、重現後立即停止
清除顯示 Ctrl+X 重設畫面顯示。在重現操作前按下可減少雜訊
Filter 對話框 Ctrl+L 新增/編輯篩選條件(第 3 章)

每一行事件由「Time(時間)、Process Name(處理程序)、PID、Operation(操作)、Path(目標路徑)、Result(結果)、Detail(詳細資訊)」組成。Operation 大致對應到 Win32 API 的粒度,例如 CreateFile(開啟/建立檔案)、ReadFile/WriteFileRegOpenKey/RegQueryValue 等等。換言之,ProcMon 的記錄檔就是「應用程式與作業系統之間對話的記錄」,應用程式原本打算讀取設定檔,但實際上讀到了哪裡,這種「意圖」與「實際」之間的落差,會直接呈現出來。

3. Filter ── ProcMon 是先篩選再閱讀的工具

若什麼都不設定就直接擷取,即使是閒置狀態的 Windows,每秒也會有數千筆事件流過。可以說 ProcMon 的實用性完全取決於 Filter 的使用方式,常規做法分為以下兩個階段。

第一階段:以處理程序篩選。 按 Ctrl+L 開啟 Filter 對話框,新增 Process Name / is / myapp.exe / Include。也可以將工具列上的準星圖示拖曳到目標應用程式的視窗上,只對該處理程序套用 Filter。

第二階段:以結果或操作篩選。 若想「尋找失敗的操作」,可設定 Result / is not / SUCCESS / Include(只顯示異常系)。若想「只看寫入操作」,可設定 Category / is / Write / Include。若想知道「是誰在存取這個設定檔」,則不篩選處理程序,直接設定 Path / contains / app.config / Include,諸如此類。

此外,實務上經常使用的還有從事件列右鍵選單進行的互動式篩選。找到一行接近目標的事件後,只需按右鍵選擇「Include ‘這個路徑’」或「Exclude ‘這個處理程序’」,不必開啟對話框,Filter 就會逐步疊加。持續用 Exclude 消除雜訊來源(防毒軟體、索引程式等),只留下目標操作前後的內容,是基本動作。輔助目視的還可以使用醒目提示(Highlight,Ctrl+H)。可以用與 Filter 相同的條件式為行加上顏色,因此當「想看整體流程,但只想凸顯異常系」時,就該用 Highlight 而不是 Filter。

有三個不知道就容易踩坑的規格。

  • Filter 只是顯示上的篩選,不是記錄上的篩選。 背後(在預設情況下)全部事件都會被記錄下來,只要取消 Filter,隨時都能回到整體視圖。這正是「非破壞性 Filter」之名的由來,其設計讓「篩選過頭而漏掉證據」的情況不易發生。1
  • Filter 設定會延續到下次啟動。 前一次調查留下的 Filter 殘留著,導致「什麼都沒顯示」而困惑,這是幾乎每個人都會經歷一次的過程。若覺得顯示異常,請先懷疑並確認 Filter 選單中的 Reset Filter(Ctrl+R)。
  • 預設已內建了幾個 Exclude。 ProcMon 本身以及分頁 I/O 等,一開始就會被排除在外。若調查需求是「不遺漏地涵蓋整個系統」,請務必意識到預設 Filter 的存在。

4. Result 欄位的判讀方式 ── 看似異常實則正常的內容

用 Filter 篩選出異常系之後,這次換成大量「看似異常的結果」湧現出來,讓人吃驚。這裡重要的是,Result 欄位中的異常值,絕大多數其實是正常運作的一部分。以下整理主要 Result 的判讀方式。

Result 意義 成為問題的可能性
SUCCESS 成功 ─(不過也有「不該成功的地方卻成功了」而成為原因的情況)
NAME NOT FOUND 該路徑上不存在該名稱 低~中。大多是搜尋順序中途的過程。若最終沒有以 SUCCESS 收尾,才是真正的主嫌
PATH NOT FOUND 途中的資料夾本身就不存在 中。是打字錯誤、資料夾未建立、環境差異的常見案例
ACCESS DENIED 拒絕存取 。權限・ACL・防毒軟體・寫入受保護區域
SHARING VIOLATION 共用違反(其他程式以獨佔方式開啟) 。檔案鎖定衝突。需鎖定相對的處理程序
BUFFER OVERFLOW 緩衝區太小,因此回傳了所需大小 。屬於正常的 API 往返(參見 FAQ)
REPARSE 沿著重新剖析點(符號連結等)追蹤 幾乎沒有。可視為路徑轉換的痕跡來閱讀
NO MORE FILES / NO SUCH FILE 列舉的結尾等 幾乎沒有

其中,成為調查主角的是 NAME NOT FOUND、ACCESS DENIED、SHARING VIOLATION 這三個。各自都有常見的調查模式,將在下一章從症狀的角度來看。

反過來容易被忽略的,是「SUCCESS 才是原因」的模式。舉例來說,「修改過的設定檔沒有生效」,答案其實是成功讀取了位於別處的舊設定檔(SUCCESS),這種情況並非一兩次。若只看異常系,就會漏掉那個被正常讀入的「錯誤的正確答案」,因此以路徑篩選、連同成功在內,把該類型檔案的所有存取都看一遍,才是穩妥的做法。

5. 依症狀分類的常見調查模式

5.1 「明明改了設定卻沒有生效」── 找出究竟是從哪裡讀取的

Path / contains / 設定檔名稱 套用 Include 後啟動應用程式,就能一覽應用程式從哪個資料夾、以何種順序搜尋該名稱的檔案。常見的真相有以下幾種:

  • 讀取的並非與 exe 相同資料夾內的檔案,而是 %APPDATA%ProgramData 底下的副本(設計上是第一次啟動時複製過去的)
  • 32 位元處理程序對登錄檔、系統資料夾的存取被 WOW64 重新導向,導致原本以為在看的位置與實際位置產生落差
  • 對安裝目標 Program Files 底下的寫入被虛擬化(VirtualStore),讀寫實際上變成了發生在別的位置

無論哪一種,ProcMon 都會在 Path 中顯示完整路徑,因此一目了然。關於設定檔存放位置該如何設計這個相反的話題,已寫在「不只是 appsettings.json ── 組態管理實務」中。

5.2 「只有這個環境無法啟動」── 追蹤 DLL 的搜尋過程

若出現啟動後立即當機、或「找不到 DLL」之類的錯誤,可以先對處理程序套用 Include,再加上 Path / ends with / .dll,觀察 NAME NOT FOUND 的連鎖情況。Windows 的 DLL 搜尋是依照固定順序遍歷資料夾,因此 ProcMon 的記錄檔中,會如實呈現出「按照搜尋順序依序出現 NAME NOT FOUND,並在某處出現 SUCCESS(或者最後都找不到)」的形式。最後都沒有 SUCCESS 的 DLL 就是犯人。反過來,「雖然 SUCCESS 了,但卻抓到了非預期位置的舊 DLL」這種模式,也是在這裡被發現的。搜尋順序的原理,請一併參閱「Windows DLL 名稱解析機制」。

COM/ActiveX 相關的「類別未登錄」問題,屬於同一類型,可以觀察到針對 RegOpenKey 之 CLSID 底下的 NAME NOT FOUND。因 32 位元/64 位元混淆而查看了不同視圖登錄檔的事故,正如「Office 2024/Microsoft 365 中 ActiveX 無法運作的原因與確認步驟」中所寫的步驟一樣,用 ProcMon 是最快的做法。

5.3 「出現 ACCESS DENIED」── 懷疑究竟是以誰的權限在運作

發現 ACCESS DENIED 時,先雙擊該事件,確認 Process 標籤頁。這裡會顯示該處理程序是以哪個使用者身分運作的,因此「服務並非以 SYSTEM 運作,而是以受限制的服務帳戶運作」「只有在工作排程器啟動時,使用者才不同」之類的落差,就能在此判明。若對象是檔案,只要與該路徑的 ACL 對照,就能確定原因。此外,若是防毒軟體介入的情況,經常能看到在前後有另一個處理程序(防毒軟體引擎)對相同路徑進行了操作,這也是以時間序列記錄的 ProcMon 才能提供的獨特證據。

5.4 「檔案處理偶爾會失敗」── 尋找 SHARING VIOLATION 的對象

共用違反是一種時間序列至關重要的調查。以路徑套用 Include、不篩選處理程序來進行擷取,在失敗的瞬間前後的行中,就會出現是誰開啟了同一個檔案。備份軟體、防毒軟體、Excel 殘留的處理程序,都是常見的對象。若要從設計上避免發生這種檔案交換上的衝突,可參閱「檔案交換的排他控制基礎知識」;Excel 處理程序殘留的問題,則整理在「C# 操作 Excel 時 EXCEL.EXE 殘留的問題」中。另外補充一點,如果只是想知道「現在這一瞬間,是誰佔用著」,比起 ProcMon,Process Explorer 的控制代碼搜尋(Ctrl+F)會更快。3

5.5 「啟動很慢」── 大致抓出時間花在哪裡

在欄位設定中新增 Duration 欄,就能看到每個操作所花費的時間。此外,也可以用 Tools 選單的 Process Activity SummaryFile Summary,依處理程序、檔案彙總操作次數與耗費時間。要抓出「啟動時執行了數萬次登錄檔讀取」「透過網路的路徑存取一直等到逾時」之類的大致方向,這樣就足夠了。不過,深入分析 CPU 用在哪裡的正式效能剖析,並非 ProcMon 的範疇。如果不是因為 I/O、而是因為運算而變慢,就該交給 PerfView 與 dotnet-trace

5.6 啟動時・登入時的問題 ── 開機記錄

若問題發生在手動啟動 ProcMon 之前,例如「服務在登入之前就失敗了」「已註冊為開機啟動的應用程式無法啟動」等情況,可以使用 Options 選單中的 Enable Boot Logging。它會記錄下次啟動時、從開機初期開始的事件,並在之後再次啟動 ProcMon 時提示儲存。開機階段記錄是作為 ProcMon 的官方功能提供的,1 在與啟動順序、登入指令碼相關的調查中,這是唯一的手段。

6. 記錄檔的儲存與交接 ── 請客戶在現場採集的情況

在不具調查的實務中,能重現問題的環境只存在於客戶端,這種情況並不少見。ProcMon 的記錄檔可以儲存為 PML 檔案,在別台機器上開啟也能看到全部欄位、全部詳細資訊,因此可以成立「由客戶負責採集,我方負責解析」的分工方式。以下是委託時使用的作業說明書範本。

  1. 以系統管理員身分執行 Procmon.exe,同意使用授權
  2. 啟動後先按 Ctrl+E 停止擷取,再按 Ctrl+X 清除顯示
  3. 按 Ctrl+E 開始擷取,重現問題的操作
  4. 重現後(或發生錯誤後)立即按 Ctrl+E 停止
  5. 選擇 File > Save,不要選 Events displayed using current filter,而是選擇 All events,以 PML 格式儲存,壓縮成 ZIP 後寄送

重點在第 5 點的「All events」。即使對方畫面上還殘留著 Filter,記錄本身仍是全量的,我方可以自由地重新篩選。若重現需要花時間、或不知道何時會發生的問題,放著不管會持續消耗記憶體,因此至少要指定以下其中一項:啟用 Filter > Drop Filtered Events,只記錄目標處理程序,或是透過 File > Backing Files 將儲存目的地從虛擬記憶體改為檔案。若不知道這兩點就放著跑一整晚,記憶體會被耗盡,導致 ProcMon 比調查對象更早達到極限。

若想自動化,也可以使用命令列開關。例如用 /AcceptEula 抑制同意對話框,用 /BackingFile 指定記錄目的地檔案,用 /Runtime 指定以秒數自動停止,用 /Terminate 終止正在執行的 ProcMon,透過這些組合,就能做到「故障發生時,操作人員只需執行一個批次檔,就能留下證據」的形式。事先決定好故障發生時該採集什麼,這種思考方式與當機傾印的採集事件記錄檔設計是共通的。

7. ProcMon 的極限,以及與其他工具的分工

ProcMon 是一款查看「操作時間序列」的工具,並非適用於所有調查場景。本公司在調查中的分工方式如下。

工具 看得到的內容 出場時機
Process Monitor 檔案、登錄檔、處理程序啟動的時間序列 依環境而異的不具問題、設定・DLL・權限・鎖定
Process Explorer 目前的處理程序・控制代碼・DLL 狀態 尋找佔用檔案的元兇、觀察控制代碼數量3
WinDbg + 傾印檔 當機・停止回應瞬間的記憶體與堆疊 例外・當機・凍結的分析
PerfView / dotnet-trace CPU 取樣・GC・記憶體配置 「速度慢」的量化調查
Application Verifier API 誤用・強制觸發異常系 出貨前的異常系測試
Wireshark / pktmon 封包內容 通訊協定層級的調查4

以下三個邊界容易讓人猶豫該用哪個工具。

  • 網路:ProcMon 會記錄 TCP/UDP 的連線、收送事件(哪個處理程序與何處通訊),但看不到封包的內容。協定層級的調查請改用 Wireshark 或 Windows 標準內建的 pktmon。4
  • 記憶體:「記憶體使用量持續增加」無法用 ProcMon 追蹤。若是受控堆積(managed heap),請進入判斷是 GC 還是洩漏的流程;若是控制代碼,則進入控制代碼洩漏調查的流程。
  • 堆疊:其實 ProcMon 也會記錄每個事件發出來源的執行緒堆疊(雙擊事件 → Stack 標籤頁),只要設定好符號,就能在程式碼層級鎖定「是誰發出了這個檔案存取」。到了這一步,就已經與 WinDbg 的世界相通,符號(PDB)的管理也就變得重要起來。

8. 結語 ── 「在閱讀程式碼之前,先看清事實」

在依環境而異的不具調查中,最先該做的事,既不是閱讀程式碼,也不是建立假說,而是採集實際發生了什麼的記錄。ProcMon 正是達成這個目標的最短路徑,只要導入 1 分鐘、擷取數分鐘,就能拿到「存取了哪個路徑、以何種順序、以何種權限、在哪裡失敗」這種無法動搖的事實。只要掌握這三點──Filter 的兩階段(處理程序 → Result)、看似異常實則正常的 Result 判讀方式、以全部事件儲存來交接記錄檔──原本因「開發機上無法重現」而停滯的調查,當天就能向前邁進一步。

本公司承接無法確定重現條件的不具調查、只在客戶環境中發生之故障的證據採集流程建置、以及結合 ProcMon、WinDbg、PerfView 的原因分析。即使目前的狀態是「記錄檔中什麼都沒顯示,但就是無法運作」,我們也能提供協助。

相關文章

相關諮詢領域

合同會社小村軟體處理因環境而異、難以重現的不具原因調查、故障發生時的證據採集流程建置,以及既有 Windows 應用程式的疑難排解支援。

參考資料

  1. Microsoft Learn, Process Monitor - Sysinternals。關於 Process Monitor 是一款即時顯示檔案系統、登錄檔、處理程序/執行緒活動的監控工具,是 Filemon 與 Regmon 的後繼者,並具備非破壞性 Filter、執行緒堆疊記錄、開機階段記錄等功能的說明。  2 3 4

  2. Microsoft Learn, Sysinternals Live。關於 Sysinternals Live 是一項無需下載工具、可透過 live.sysinternals.com/ 的網址或檔案共用直接執行工具的服務的說明。 

  3. Microsoft Learn, Process Explorer - Sysinternals。關於 Process Explorer 能顯示處理程序所開啟的控制代碼與已載入的 DLL,並可用於搜尋哪個處理程序開啟了特定檔案或目錄的說明。  2

  4. Microsoft Learn, Packet Monitor (Pktmon)。關於 Windows 標準內建的封包擷取工具 Packet Monitor 的概要與用途的說明。  2

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

本文連結到以下服務頁面,歡迎從最接近的入口查看。

常見問題

整理諮詢這個主題時常見的問題。

在正式環境上執行 ProcMon 安全嗎?
短時間的擷取在實務上很常見,但並非無條件安全。ProcMon 會載入驅動程式並記錄大量事件,因此在事件發生量大的伺服器上,會明顯消耗 CPU 與記憶體。對策有三個:(1) 在重現操作前才開始擷取、重現後立即停止,將擷取時間縮到最短;(2) 若需要長時間監控,啟用 Filter 選單中的 Drop Filtered Events,不保留 Filter 之外的事件;(3) 透過 Backing File 將記錄目的地設定為檔案而非記憶體。此外,建議將其排入與一般變更作業相同的核准流程,例如安排在非上班時段執行,或在取得快照之後再進行。
事件太多,找不到想要的那一行。該如何篩選?
常見做法是先用 Process Name 對目標處理程序套用 Include,再用 Result 篩選出異常系(NAME NOT FOUND、ACCESS DENIED 等)。找到一行接近目標的事件後,可在該行按右鍵,透過顯示出的 Include 或 Exclude 進行互動式篩選。另一方面,也常見「篩選後才儲存,結果資訊不足」的失敗案例,因此若要將記錄檔存檔交給他人,請記得 Filter 只是顯示上的篩選,儲存時應保存全部事件。另外,Filter 設定會延續到下次啟動,若出現「畫面上什麼都沒有」的情況,請先透過 Filter 選單的 Reset Filter 確認是否殘留了上次的舊 Filter。
Result 欄位出現的 BUFFER OVERFLOW 是臭蟲或攻擊的徵兆嗎?
不是。這與資安術語中的緩衝區溢位攻擊無關,而是「呼叫端準備的緩衝區比實際需要的資料小,因此系統回傳了所需大小」的一次正常 API 往返。許多 API 的設計是先以較小的緩衝區呼叫一次以取得所需大小,再重新配置並再次呼叫,因此只要緊接著在同一路徑上出現 SUCCESS,就沒有問題。同樣地,NAME NOT FOUND 大多也只是「在搜尋順序途中沒找到」的過程,只要最終在某處出現 SUCCESS,就不算異常。異常系的 Result 唯有在確認「該操作的失敗是否與應用程式的症狀之間存在因果關係」之後,才能稱之為原因。
Process Explorer 與 Process Monitor 該如何分工使用?
Process Monitor 是以時間序列記錄「操作的流程(何時、哪個處理程序、對哪個路徑、做了什麼、結果如何)」的工具;Process Explorer 則是查看「此刻當下的狀態(哪個處理程序開啟了哪些檔案或 DLL、CPU 與記憶體的使用狀況)」的工具。舉例來說,若想知道「這個檔案無法刪除,是誰佔用了它」,用 Process Explorer 的控制代碼搜尋最快;若想知道「應用程式何時、以何種順序讀取這個檔案」,則該用 Process Monitor。實務上建議將兩者都作為 Sysinternals Suite 的常備工具,並記住:狀態看 Process Explorer,歷程看 Process Monitor,這樣就不會迷失方向。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽