简介:《Process Monitor 使用说明》是一份面向 IT 运维、桌面支持与安全排障人员的实操文档,聚焦利用 Sysinternals 工具监视文件、注册表、进程与线程活动,并围绕 IPGuard/ip-guard 场景梳理事件采集与问题定位思路。压缩包内共 1 个 docx 文件,大小约 84KB,内容以步骤化说明和界面操作提示为主,便于按流程快速上手。该资料已有 696 人学习,适合需要排查软件冲突、权限异常、访问拦截或系统性能瓶颈的读者参考。文档围绕采集前准备、过滤条件设置、问题复现、数据保存与结果分析等环节展开,能帮助读者减少无关事件干扰、定位关键访问行为,并形成可复用的排错记录。
1. 采集十分钟导出 1.8GB,翻遍日志却没有一条目标进程的事件
某开发者把 Process Monitor 的采集结果发过来,压缩包解开将近 2GB,打开翻了二十多分钟,屏幕上滚的全是后台服务读写临时目录、组件缓存、更新检查,真正要查的那次点击操作一条都没留下。他说自己完全照着内部说明走的:关软件、开工具、停采集、清空、复现、保存,步骤一条没落,结果还是白抓。
Process Monitor 的坑大多不在工具本身,而在采集流程的时序上——早开三十秒、晚停一分钟、清空时没确认、保存时没核对末尾时间戳,任意一处差半拍,日志里就是几十万条噪音盖住那几十条关键事件。下面这几个场景,是现场排查终端管控客户端与业务程序冲突时最容易翻车的地方,适合正在被“抓不到、抓到了看不懂、看懂了用不上”卡住的运维和开发。
2. 采集前没做干净:旧事件、没停采集、配置被重置
这一章处理三个源头问题:开始采集前目标软件到底该不该关、点击放大镜之后怎么确认真的停了、以及启动时那个提示“是否重置”的弹窗到底动了什么。这三件事任何一件没做对,后面抓到的数据都会掺进大量与复现无关的事件,分析阶段再想补救基本只能重抓。
现场最常见的对话是“我明明抓到问题了,分析时找不到”。多数情况下,并非工具没记录,真正的原因是记录被稀释,或者记录的点根本不对。
2.1 先关软件再开工具:顺序反了丢掉的不只是噪音
Process Monitor 一经启动就开始记录全系统事件,业务程序闲着也会有心跳、日志轮转、配置回读,一秒几千条。如果目标软件已经在跑,你抓到的第一批事件全是这些周期性动作,跟复现的问题毫无关系。更隐蔽的损失在于:软件启动阶段会读取配置、加载模块、注册表项,这些恰恰是排查“程序起不来、起来就崩”最难补的素材,一旦先启动再开工具,这段记录就永远拿不回来了。
所以顺序必须是:关掉目标软件 → 启动 Process Monitor 并停采集、清空 → 设置过滤器 → 启动软件 → 复现问题 → 停采集 → 保存。原始说明里那句“重置确定后,再按照步骤 1 操作”,其实就是这个意思:重置之后过滤器回到全放行状态,中间已经记录的全是噪音,与其接着抓,不如从头再来一遍干净流程。
用命令行启动能让这套动作更稳定,避免每次靠手点、点错状态:
# 以管理员身份启动 Process Monitor,静默接受协议、最小化、事件实时落到指定文件 $procmon = "C:\Tools\Procmon\Procmon64.exe" $pml = "D:\capture\case.pml" # /AcceptEula 免掉首次启动的协议弹窗;/Quiet 抑制过程中的提示框 # /Minimized 最小化到托盘,避免挡在业务窗口上 # /BackingFile 让事件直接写磁盘,不再全靠内存缓冲,长时间采集不容易丢事件 Start-Process -FilePath $procmon -Verb RunAs -ArgumentList @( "/AcceptEula", "/Quiet", "/Minimized", "/BackingFile", $pml )这段脚本的关键在-Verb RunAs和/BackingFile两处。前者解决权限,不提权会漏掉一大半事件,下一章细说;后者解决容量,事件不落盘就只能在内存里打转,缓冲区满了就丢。/Minimized看着无关紧要,实际能避免一个尴尬:窗口盖在业务软件上,员工复现时点错位置,日志里就多了一堆无关的窗口切换事件。
关软件也不等于关窗口。业务程序通常还挂着托盘进程、升级服务、日志采集子进程,主窗口关了它们照跑,复现时抢先处理文件、占着配置目录,抓出来的结果和单进程环境完全不一样。我一般先看一遍再动手:
# 目标软件常有托盘进程、升级服务同时存在,只关主窗口等于没关 Get-Process -Name "TargetApp*" -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime, Path # 确认没有正在写日志、占文件的残留进程后再继续采集 Stop-Process -Name "TargetApp*" -Force -ErrorAction SilentlyContinueStartTime这一列值得留意:如果某个进程的启动时间比主程序早很多,多半是常驻服务,光关主窗口它不会退出,得单独结束。-ErrorAction SilentlyContinue是为了在进程列表为空时不报错,脚本能一条路走到底,不会中途断掉让采集流程停在半截。
2.2 停采集、清空、确认:红叉才是停
放大镜图标是最容易读错状态的控件。没有红叉时表示正在捕获,点一下变成带红叉的放大镜,才表示已停止。不少人默认“点一下就是开始”,结果把本来在跑的采集又停了,或者以为停了其实还在跑,复现操作和后续所有事件全混在一起。
清空用Ctrl+X,工具栏上也有对应的清除按钮。清空之后要有个确认动作:事件列表应该是空的,底部状态栏的事件计数归零。如果列表空了但计数还在涨,说明采集没停,Ctrl+X只是把显示清掉了,新事件立刻又填进来。
我在现场会用下面这张表逐项过一遍,不靠感觉判断:
| 检查点 | 操作 | 成功标志 |
|---|---|---|
| 采集状态 | 点工具栏放大镜 | 图标带红叉,状态栏计数不再增长 |
| 事件列表 | Ctrl+X清空 | 列表为空,事件数为 0 |
| 过滤器 | Ctrl+L打开过滤器窗口 | 只剩目标规则,没有残留的排除项 |
| 时间基准 | 记录开始时刻 | 复现动作能与日志时间轴对齐 |
第三项经常被漏掉。上次排查留下的过滤器可能还挂着某个进程名,这次排查的是另一个程序,结果新进程的事件全被排掉,日志干干净净一条没有,看起来像工具坏了。第四项是给事后分析留退路,采集开始、复现开始、复现结束三个时间点记下来,后面在几百万条事件里裁剪区间时就靠它。
# 分别记录三个时间点,后续在日志里按区间裁剪,比凭记忆找快得多 $captureStart = Get-Date "采集开始: {0:yyyy-MM-dd HH:mm:ss.fff}" -f $captureStart # ……此处让员工复现问题…… $reproEnd = Get-Date "复现结束: {0:yyyy-MM-dd HH:mm:ss.fff}" -f $reproEnd "总耗时: {0:N1} 秒" -f ($reproEnd - $captureStart).TotalSeconds时间戳精确到毫秒是有必要的,同一秒里可能发生上百次文件操作。总耗时那一行还兼着另一个作用:员工说“我操作了五分钟”,实际脚本显示四十秒,说明中间有停顿或者操作被跳过了,采集结果的可信度要打个折扣,这一点比事后分析日志更早暴露问题。
2.3 启动时弹出重置提示:配置读不到,过滤器被清掉
那个“是否重置”的弹窗,通常出现在配置文件加载失败的时候。Process Monitor 会把上次的过滤器、列设置、高亮规则存在用户配置目录里,启动时读回来。触发读取失败的条件不少:换了登录账户、工具被拷到只读介质或共享目录、配置目录权限被收紧、上次异常退出把配置文件写坏。点了确定之后,过滤器回到全放行的默认状态,之前精心调好的规则一条不剩。
这就是为什么原始说明强调“重置确定后,再按照步骤 1 操作”。重置本身没让工具变差,它只是把过滤条件清空了,接着复现就会抓到全系统噪音,和从头再来没有区别,还不如老老实实重走一遍。
根治办法是把过滤器固化成文件,每次启动直接加载,不依赖用户配置目录:
$pmc = "D:\capture\baseline.pmc" # 事先在 Filter 对话框里调好并另存 if (-not (Test-Path $pmc)) { throw "过滤器配置缺失,先在 Filter 窗口调好并另存一份,再启动采集" } & "C:\Tools\Procmon\Procmon64.exe" /AcceptEula /Quiet /Minimized ` /LoadConfig $pmc ` /BackingFile "D:\capture\case.pml"/LoadConfig加载的是配置文件,里面带着过滤器和界面设置。前面加一段Test-Path判断,是因为配置缺失时工具不会报错,它会安安静静退回默认配置,你以为规则生效了,其实一条都没有——这种静默失败在现场最难查,等发现的时候采集早就结束了。
如果配置文件反复被重置,可以顺手确认一下配置目录的写入权限,或者干脆把工具和配置一起放在固定路径,用同一账户运行。工具装在临时目录、桌面、U 盘上,换个人接手就出问题,这类“环境漂移”导致的采集失败,比重装系统还难解释。
3. 抓不到目标进程:Access Denied、过滤器写错、进程一闪而过
采集流程干净了,下一个坎是“目标进程根本没出现在日志里”。这一章的三节分别对应三种成因:权限不够导致事件缺失、过滤器规则顺序写反导致事件被排掉、进程存活时间太短导致事件还没来得及记录。三种情况在日志上的表现完全不同,认准了再动手,比反复重抓有效得多。
3.1 以管理员身份运行:权限不足时的三种症状
非提权启动不会直接报错,它只是安静地少记一部分东西。第一种症状是 Result 列出现大量ACCESS DENIED,但业务其实跑得好好的——这些是工具自身没权限读取某些对象时记录的探测失败,属于假阳性,照着它去改权限只会越改越乱。第二种症状更彻底:受保护进程、SYSTEM 上下文跑的服务,在日志里连名字都搜不到。第三种是能看见进程,但 Path、Detail 两列为空,事件只剩个壳。
标准做法是全程以管理员身份运行,同时打开调试特权,让工具能拿到更多进程句柄:
# 采集前先确认提权状态,非提权会话下抓到的事件会缺一大块 $isAdmin = ([Security.Principal.WindowsPrincipal] ` [Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { "当前未提权,建议重开一个管理员会话再采集" } else { "已提权,可以开始采集" }判断逻辑走的是 Windows 主体对象,跟当前账户是不是管理员组成员无关——UAC 下管理员账户的普通会话照样返回False。这一点经常被误解:账户是管理员,权限却没生效,事件照样缺。
调试特权在 Options 菜单里,勾上之后工具能打开更多受保护进程的句柄。它会略微增加系统开销,排查完记得关掉,长期开着没有意义。
3.2 过滤器怎么写:先排除噪音,再包含目标
过滤器是这个工具最反直觉的部分。规则从上往下一行行比对,第一条命中的规则直接决定这条事件留下还是丢掉,后面的规则不再参与判断。也就是说,顺序即逻辑:把“包含目标进程”写在“排除系统进程”前面,一旦某条svchost.exe的事件先撞上包含规则,它就被留下了,后面的排除规则形同虚设。
正确的写法是先砍噪音,再放行目标:
# 规则按书写顺序自上而下匹配,第一条命中即决定去留 # 所以排除噪音必须排在包含目标之前,顺序反了等于没排除 & "C:\Tools\Procmon\Procmon64.exe" /AcceptEula /Quiet /Minimized ` /Filter "Process Name is svchost.exe then Exclude" ` /Filter "Process Name is explorer.exe then Exclude" ` /Filter "Process Name is TargetApp.exe then Include" ` /Filter "Path contains \TargetApp\ then Include"前两条把系统里最吵的两个进程排掉,第三条放行目标程序,第四条兜底放行目标程序的数据目录——有些事件由子进程发起,进程名对不上但路径对得上,靠这条能捞回来。不同语言版本的字段名可能显示不一样,稳妥做法是先在过滤器对话框里把规则调好、验证有效,再把同样的规则写进脚本,或者直接保存成.pmc用/LoadConfig加载。
筛选维度不用贪多,四五个就够:
| 维度 | 典型用法 | 适用场景 |
|---|---|---|
| Process Name | is TargetApp.exe Include | 只关心单个程序 |
| Path | contains \ProgramData...\ Include | 盯某个配置或数据目录 |
| Result | is ACCESS DENIED Include | 查权限、查拦截 |
| Operation | is CreateFile Include | 查文件打开失败 |
| PID | is 1234 Include | 多会话下同名进程区分 |
判断效果的标准很直接:复现一次,日志条数应该从几十万降到几百到几千。如果还是六位数,说明排除规则没生效,先回去检查顺序,别急着分析。
3.3 进程启动即退出:把“启动”这一刻留在缓冲里
最让人抓狂的情况是双击程序,窗口闪一下没了,日志里连进程名都搜不到。原因很朴素:进程存活时间比你点“停止”的反应时间还短,或者它启动时你正在做别的操作,那几十条关键事件已经被后面的噪音挤出缓冲区。
第一招是承接 2.1 的顺序,先挂工具再启动程序,让启动阶段的 CreateFile、RegOpenKey、LoadImage 全部落在日志里。第二招是打开进程树(Tools 菜单里),能看到进程的完整生命周期和父子关系,子进程起来又立刻消失的情况一目了然。第三招适合开机就崩的场景:启用引导日志,重启后从引导阶段开始记录,连驱动加载都能抓到。
窗口上的十字准星图标也值得用一次。把它拖到目标程序窗口上,过滤器会自动加一条该进程的规则,省得手写进程名写错。这个动作在员工面前显得专业是一方面,更重要的是快,能赶在程序退出前把规则挂上。
需要长时间守着的场景,交给定时参数:
# /Runtime 到点自动退出,事件已经在 backing file 里 # 人离开工位也不会一直抓到把磁盘写满 & "C:\Tools\Procmon\Procmon64.exe" /AcceptEula /Quiet /Minimized ` "/BackingFile" "D:\capture\boot_case.pml" ` "/Runtime" "300"/Runtime的单位是秒,300 表示五分钟后工具自行退出,已记录的事件保留在 backing file 里,直接就是最终日志。用引导日志配合这个参数要特别注意:引导日志会在下次启动时自动开始记录,不主动关掉就会每次开机都写盘,时间一长系统盘悄悄少掉几个 GB,这是很多人踩过的坑。
4. Events have been lost:缓冲区溢出、事件丢失与磁盘被写满
日志长度和完整性是两回事。日志几百万条,不代表关键那几十条还在里面。事件丢失有明确的征兆,也有对应的调节手段,麻烦的是它往往不报错,只在状态栏给个小提示,或者干脆什么都不说,你只能靠时间轴上的空洞推断出来。
4.1 事件丢失的触发条件与提示长什么样
状态栏出现事件丢失提示是最直接的信号,但很多人没注意到,因为它在窗口最底部,字体又小。更常见的证据是时间轴断层:日志里 14:32:10 之后直接跳到 14:32:47,中间三十七秒空白,而员工说那段时间他一直在点保存按钮。复现操作明明做了,对应时间点什么都没有,八成就是这段被丢了。
触发条件集中在三种。一是事件产生速率超过写入速率,编译、大文件解压、杀毒全盘扫描任意一件事同时在跑就够了。二是没启用 backing file,全靠内存缓冲,缓冲一满就丢,丢完继续记录,日志看起来完好无损。三是过滤器太宽,系统噪音占满缓冲,真正的事件挤不进去就没了。另外,线程剖析这类事件量级本来就大,除非专门查线程卡顿,开着只会加速丢失。
分析阶段发现丢事件,只能重抓,没有后悔药。所以判断应该放在采集阶段:复现前后各看一眼状态栏,有没有丢失提示,时间轴有没有断层。
4.2 缓冲区、监控类别与落盘位置三处调节
第一处是缓冲大小。较新版本在 Options 里可以直接调,默认是几十兆的量级,对长时间采集明显不够;找不到入口的版本,就用 backing file 绕开内存瓶颈,效果一样。
第二处是监控类别。网络事件默认不开,只有排查共享目录访问、接口调用超时才需要启用,开了之后事件量会明显上涨。线程剖析同理,查性能瓶颈时才开。关掉用不上的类别,是成本最低的减量手段。
第三处是落盘位置,也就是 backing file 放哪。放在系统盘的临时目录最省事,也最容易把盘写满,后面 4.3 细说。
还有一个小开关常被忽略:丢弃已过滤事件。勾上之后,被过滤器排除的事件直接扔掉,不进缓冲,内存占用立刻降下来。它和 3.2 的过滤器是配套的,规则写得好,这个开关才有意义。
# 采集中途监控 backing file 体积与剩余空间,防止写到一半盘满 $pml = "D:\capture\case.pml" $minFree = 5GB while ($true) { if (Test-Path $pml) { $size = [math]::Round((Get-Item $pml).Length / 1MB, 1) $free = (Get-PSDrive D).Free "{0} 日志={1} MB 剩余={2} GB" -f ` (Get-Date -Format "HH:mm:ss"), $size, [math]::Round($free / 1GB, 2) if ($free -lt $minFree) { "剩余空间不足 5GB,先停采集再换盘" break } } Start-Sleep -Seconds 30 }$minFree这个阈值不是随便定的,采集本身失败是小事,磁盘写满连带页面文件、系统事件日志一起写不进去,机器会开始各种异常,现场解释起来很被动。Start-Sleep给 30 秒是权衡后的值:更短没必要,文件增长没那么快;更长的间隔可能一觉醒来盘就满了。这个脚本放在旁边跑着,不占资源,也不用一直盯着工具界面。
4.3 长时间采集:别让日志把系统盘撑爆
backing file 默认可能落在临时目录,也就是系统盘。一次三分钟的操作复现,几百兆;十分钟的业务流程走查,两三个 GB 很常见;开机崩溃场景挂上引导日志,十几个 GB 也不稀奇。这些体积和事件速率强相关,预判不准,只能靠预留空间来兜底。
| 场景 | 典型时长 | 事件量级 | 落盘建议 |
|---|---|---|---|
| 单次操作复现 | 1~3 分钟 | 几十万 | 系统盘临时目录可承受 |
| 业务流程走查 | 10~30 分钟 | 数百万 | 非系统盘,预留 5GB 以上 |
| 开机崩溃排查 | 引导到桌面 | 视驱动加载量而定 | 非系统盘,预留 10GB 以上 |
采集之前先算账,比写到一半再挪文件靠谱:
# 采集前检查目标盘空间,顺手把目录建好,避免保存时找不到路径 $target = "D:\capture" $freeGB = [math]::Round((Get-PSDrive D).Free / 1GB, 2) "目标目录: $target 剩余: $freeGB GB" if (-not (Test-Path $target)) { New-Item -ItemType Directory -Path $target | Out-Null } if ($freeGB -lt 5) { "空间不足,建议换盘或缩短采集时长" }盘符写死在脚本里不算优雅,但现场够用。真正要避免的是把 backing file 放在%TEMP%然后忘了这回事,采集结束文件还在,下次系统盘告警时才发现角落里躺着几个 8GB 的旧日志。养成采集完立刻归档到指定目录的习惯,比事后翻磁盘找文件省事得多。
5
本文还有配套的精品资源,点击获取