排错实战——通过对比分析sysinternals事件修复程序功能异常

简介: 解决问题的思路很重要

缘起

最近,我们程序的某个功能在一台机器上不正常,但是在另外一台机器上却是正常的。代码是同一份,vs版本也一样(打的补丁也一样)。编译出来的程序在两台电脑上运行的结果就是不一样。惊不惊喜,意不意外?如果是你遇到了这种情况,你会怎么调查呢?:upside_down_face:

说明:
为了跟大家分享这个问题,我事后在自己的机器上重新把整个过程梳理了一遍,并保存了 process monitor抓取的事件文件,方便感兴趣的读者亲手做实验。
为了行文方便,下文把程序功能正常的电脑称作 A,把程序功能不正常的电脑称作 B

排查问题

通过对比程序在两台电脑上的运行过程的不同点可以比较有效的解决这种问题。

下面是我的思路:

  • 首先,排除代码不一致的问题。把A上的代码拷贝到B上,编译,运行,功能不正常。
  • A上的整个Debug目录(程序所在的目录)拷贝到B上,运行,依然不正常。
  • 对比两台电脑上的环境变量,排除两台电脑的环境变量不一致导致的问题(尤其是PATH,会影响dll加载顺序)。

经过以上几步,问题还是没能得到解决。B应该还有某个(些)关键点A不一样。但是这个(些)关键点究竟是什么?我们应该怎么找到它(们)?这时候该本文的主角process monitor闪亮登场啦!

请出process monitor

在开始前,先跟各位读者介绍下process monitor的事件分类:

process monitor捕获的事件总共分为 5 类:

  • Registry Activity 注册表相关事件(键和值的读写,创建,删除,枚举等)
  • File System Activity 文件系统相关事件(本地存储和远程文件系统相关事件)
  • Network Activity 网络相关事件(TCP和UDP网络活动)
  • Process and Thread Activity 进程及线程事件(进程和线程事件,模块加载)
  • Profiling Event(我没用过,具体可参考书上的介绍)

为了方便大家获得更详细的介绍,特意从《Troubleshooting with the Windows Sysinternals Tools》(英文版)中截了一张图:

class of events 截自《Troubleshooting with the Windows Sysinternals Tools》(英文版)

捕获Event data

首先,使用process monitor分别在AB上捕获Event Data。这里不贴出使用process monitor捕获的过程了。操作很简单,在之前的文章([[原]为IDA加载调试符号])里有录屏。

好了,拿到了Event Data,接下来我们应该怎么对比呢?

对比分析Event Data

在对比前,我们应该过滤掉无关的事件(因为process monitor捕获到的事件实在是太多了),这里我只根据进程名进行了基本的过滤。

过滤完成后,我们从五类事件中的File System事件看起(没想到直接解决了问题,剩下几个不用看了:smirk:)。

对比图如下(左侧是A,右侧是B):

filesystem-event-compare

Wow, 从图中我们明显可以看出来,A成功加载了pgcell.ocxB没有加载。有windows COM组件开发经验的读者一定想到了,B上没注册pgcell.ocx

解决问题

知道问题的原因,剩下的事情就很好办了。在B上注册pgcell.ocx。注册成功后,在程序里重新执行对应的功能,一切正常。搞定收工。

为了方便对windows COM组件开发不熟悉的读者,这里给出注册脚本(#后面的是注释) 。

cd path/to/pgcell.ocx
regsvr32 pgcell.ocx
# regsvr32 -u pgcell.ocx  # unregister pgcell.ocx

关于regsvr32的更多用法,可以直接运行regsvr32进行学习。在我机器上运行后的截图如下:

regsvr32-u

通过regsvr32给出的提示,相信聪明的你也可以自己写一个COM组件的注册和卸载工具。如果对这方面有兴趣,欢迎留言交流。

后记

最开始帮同事解决这个问题的时候,没有用process monitor,而是使用了process explorer。在继续阅读下面的文章前,请先停下来好好思考一下,如何使用process explorer排查此问题?

和使用process monitor一样,我们需要对比程序在AB上有什么不同。话不多说,请看动态对比图:

A上的运行过程:

procexp-good

B上的运行过程:
procexp-bad

我们可以发现,A上能成功加载pgcell.ocxB却没有加载。

能使用process explorer解决这个问题,多少有运气的成分!因为这个问题恰巧是由于加载不上某个dll导致的。如果是由于其它原因(e.g. 读取不到某个关键文件),使用process explorer就没那么容易发现问题所在了。

总结

  • 遇到问题,我们需要清晰的思路+合适的工具
  • 程序在一台电脑上运行正常,在另外一台上运行不正常。对比程序在两台电脑上的运行过程的不同点应该是解决这种问题的有效办法。
  • sysinternals系列工具,真的是排错神器!你值得拥有!
  • 一定要好好利用process monitor的过滤功能!能不能有效的过滤出我们想要的事件是重中之重!

参考资料

阅读完今天的文章,你有什么收获吗?欢迎留言交流!

相关文章
|
4天前
|
测试技术 开发工具 git
写了BUG还想跑?---闲鱼异常日志问题自动追踪-定位-分发机制
为了高效地发现、定位和解决预发问题,闲鱼团队研发了一套异常日志问题自动追踪-定位-分发机制。这套机制通过自动化手段,实现了异常日志的定时扫描、精准定位和自动分发,显著降低了开发和测试的成本,提高了问题解决的效率。
写了BUG还想跑?---闲鱼异常日志问题自动追踪-定位-分发机制
|
7月前
|
安全 Linux 开发者
⭐⭐⭐⭐⭐Linux C/C++ 进程崩溃诊断以及有效数据收集:解锁代码问题快速定位与修复的方法
⭐⭐⭐⭐⭐Linux C/C++ 进程崩溃诊断以及有效数据收集:解锁代码问题快速定位与修复的方法
428 1
|
4月前
|
Cloud Native 数据处理
项目环境测试问题之当异步任务在运行过程中抛出非预期的异常会导致后果如何解决
项目环境测试问题之当异步任务在运行过程中抛出非预期的异常会导致后果如何解决
|
4月前
|
存储 缓存 JavaScript
Electron V8排查问题之V8FatalErrorCallback崩溃问题的定义如何解决
Electron V8排查问题之V8FatalErrorCallback崩溃问题的定义如何解决
46 0
|
5月前
|
JSON 监控 安全
优化Java应用程序的日志记录和跟踪
优化Java应用程序的日志记录和跟踪
|
SQL 前端开发 测试技术
一次纯线上接口异常的排查过程
一次纯线上接口异常的排查过程
147 0
|
7月前
|
测试技术
需求不明确的情况下,测试该如何处理?
需求不明确的情况下,测试该如何处理?
133 0
|
7月前
|
JavaScript IDE Java
bugly崩溃排查3:观察是谁调用了崩溃函数
bugly崩溃排查3:观察是谁调用了崩溃函数
77 0
VS2017诊断工具意外失败处理方法
VS2017诊断工具意外失败处理方法
VS2017诊断工具意外失败处理方法
|
存储 监控 数据可视化
01.崩溃捕获设计实践方案
01.崩溃捕获设计实践方案
189 3