原调试debug排错troubleshootprocess monitorsysinternals

缘起

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

{% note info %}

说明:

为了跟大家分享这个问题,我事后在自己的机器上重新把整个过程梳理了一遍,并保存了process monitor抓取的事件文件,方便感兴趣的读者亲手做实验。

为了行文方便,下文把程序功能正常的电脑称作A,把程序功能不正常的电脑称作B

{% endnote %}

排查问题

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

下面是我的思路:

  • 首先,排除代码不一致的问题。把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 ),接下来我们应该怎么对比呢?

对比分析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上的运行过程:


good

B上的运行过程:

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

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

总结

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

参考资料

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

[原]排错实战——通过对比分析sysinternals事件修复程序功能异常的更多相关文章

  1. [原]排错实战——解救加载调试符号失败的IDA

    原调试IDA排错troubleshootsymbolspdbsysinternalprocess monitor 缘起 最近想借助IDA逆向一个函数.在windows下,调试器(比如vs, windb ...

  2. [原]排错实战——使用process explorer替换任务管理器

    原Aha总结注册表process explorersysinternalsprocess monitor 前言 一般,我们会使用任务管理器查看系统中有哪些进程正在运行,强制杀掉某个进程.可是系统自带的 ...

  3. [原]排错实战——VS清空最近打开的工程记录

    原脚本how-toprocess monitorsysinternalsvsvisual studiovs2017vs2019注册表 缘起 vs有一个功能 -- 在起始页会显示最近打开的工程列表,方便 ...

  4. [原]排错实战——解决Tekla通过.tsep安装插件失败的问题

    原总结调试排错troubleshootteklaprocess monitorsysinternals 缘起 最近同事使用.tsep安装Tekla插件的时候,Tekla提示该插件已经存在了,需要卸载后 ...

  5. 前端基本知识(一):W3C标准&&冒泡事件,捕获事件,W3C DOM对象模型,对比分析

    W3C标准是万维网联盟, 其他的可以参考万维网版本的更新内容 一.W3C标准 二.W3C DOM事件 三.冒泡事件 四.捕获事件 一.W3C标准 其实网页是由三分部组成:1.结构(structure) ...

  6. 第15.17节 PyQt(Python+Qt)入门学习:PyQt图形界面应用程序的事件捕获方法大全及对比分析

    老猿Python博文目录 老猿Python博客地址 按照老猿规划的章节安排,信号和槽之后应该介绍事件,但事件在前面的随笔<PyQt(Python+Qt)实现的GUI图形界面应用程序的事件捕获方法 ...

  7. Apache 流框架 Flink,Spark Streaming,Storm对比分析(一)

    本文由  网易云发布. 1.Flink架构及特性分析 Flink是个相当早的项目,开始于2008年,但只在最近才得到注意.Flink是原生的流处理系统,提供high level的API.Flink也提 ...

  8. Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

    文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...

  9. Spring Boot 实战与原理分析视频课程

    Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...

随机推荐

  1. SecureCRT打开文件中文乱码

    1.菜单:option(选项): 2.选择session options(会话选项): 3.打开的窗口中,点击Appearance(外观): 4.页面上:character encoding(字符编码 ...

  2. PHP ~ 设置和读取 Cookie

    一,设置 Cookie setcookie("user",$user,time()+3600);     // user 为用户名,$user 为变量的值   二,读取 Cooki ...

  3. 【LeetCode】最长公共子序列

    [问题]给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子串,并返回其长度.例如:A = "HelloWorld"B = "loop"则A与B的最 ...

  4. 17. react redux的中间件

    1. redux 数据流程图 View 会派发一个 Action Action 通过 Dispatch 方法派发给 Store Store 接收到 Action 连同之前的 State 发给  Red ...

  5. Dubbo与Zookeeper 简介

    转自http://blog.csdn.net/congcong68/article/details/41113239 首先说一下Dubbo解决什么问题: (1)当服务越来越多时,服务Url配置管理变得 ...

  6. Python风格规范分享

    今天给大家分享Python 风格规范,以下代码中 Yes 表示推荐,No 表示不推荐. 分号 不要在行尾加分号, 也不要用分号将两条命令放在同一行. 行长度 每行不超过80个字符 以下情况除外: 长的 ...

  7. OpenResty从入门到开发一个网关服务(使用etcd作为注册中心)

    简介 OpenResty(也称为 ngx_openresty)是一个全功能的 Web 应用服务器.它打包了标准的 Nginx 核心,很多的常用的第三方模块,以及它们的大多数依赖项. 通过揉和众多设计良 ...

  8. C#高级编程(第9版) 第08章 委托、lambda表达式和事件 笔记

          本章代码分为以下几个主要的示例文件: 1. 简单委托 2. 冒泡排序 3. lambda表达式 4. 事件示例 5. 弱事件     引用方法 委托是寻址方法的.NET版本.在C++中函数 ...

  9. Python基本数据类型之字符串

    Python转义字符 在需要在字符中使用特殊字符时,python用反斜杠(\)转义字符.如下表: 转义字符 描述 \(在行尾时) 续行符 \\ 反斜杠符号 \' 单引号 \" 双引号 \a ...

  10. JavaBean和json数据之间的转换(一)简单的JavaBean转换

    1.为什么要使用json? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,因为其高性能.可读性强的原因,成为了现阶段web开发中前后端交互数据的主要数据 ...