Windows开发值得推荐的分析工具,值得收藏

目录

1、概述

2、常用工具介绍

2.1  窗口查看工具SPY++

2.2  Dependency Walker

2.3  剪切板查看工具Clipbrd

2.4  GDI对象查看工具GDIView

2.5  Process Explorer

2.6  Prcoess Monitor

2.7  API Monitor

2.8  调试器Windbg 

2.9  反汇编工具IDA 

2.10  抓包工具Wireshark

3、总结


下面我们就来聊一聊,作为Windows开发人员,我们都需要掌握哪些常用的软件分析工具。 

1、概述

图片[1]-Windows开发值得推荐的分析工具,值得收藏-卡核

       在Windows软件的日常开发和维护的过程中时,常会用到一些常用的工具来辅助分析和解决我们遇到的各种各样的软件异常问题。常用的工具有SPY++、Dependency Walker、剪切板查看工具Clipbrd、 GDI对象查看工具GDIView、Process Explorer、Process Monitor、API Monitor、Windbg异常分析工具、IDA交互式反汇编工具、Wireshark抓包工具等。本文将结合具体的案例及实际场景,对上述工具进行一个详细的介绍。

2、常用工具介绍

2.1  窗口查看工具SPY++

图片[2]-Windows开发值得推荐的分析工具,值得收藏-卡核​​​​​​​       SPY++是微软Visual Studio自带的工具,该工具可以查看当前系统中打开的所有窗口信息,在分析窗口问题时该工具比较常用,在我们的日常开发中会经常使用。一般我们使用该工具来查看窗口的位置、大小、窗口样式、父窗口等信息。

图片[3]-Windows开发值得推荐的分析工具,值得收藏-卡核

对于可见的窗口,可以直接将探测按钮移动到目标窗口上,直接查看目标窗口的信息。对于掩藏的、不可见的窗口,也可以直接在SPY++的窗口列表中以窗口标题、类名、窗口句柄等关键字去搜索目标窗口。

        可以将当前窗口列表中所有的窗口信息保存到文件中,操作入口如下所示:

图片[4]-Windows开发值得推荐的分析工具,值得收藏-卡核

这在分析窗口异常崩溃的问题会很有用。

2.2  Dependency Walker

        Depenency Walker是库依赖查看工具,可以查看dll库的导出接口信息,也可以查看exe和dll的依赖库信息。该工具是早期Visual Studio自带的工具,现在的Visual Studio不再打包该工具了,需要到Depenency Walker官网上去下载。

        该工具主要用于排查程序启动时缺少库报错、找不到接口报错等问题。比如弹出如下的错误提示框:

图片[5]-Windows开发值得推荐的分析工具,值得收藏-卡核

图中提示找不到MSVCP100D.dll运行时库(D对应debdebug版本的运行时库),程序是release版本的,怎么会依赖debug版本的运行时库呢?估计是底层依赖的dll库(底层的库包括底层的网络库、协议库、组件库等)发布的有问题,错把debug版本的库发布到我们release版本的exe产品流上了。此时可以用Dependency Walker打开exe程序,查看其依赖的库,看看哪个库依赖了的debug版本的MSVCP100D.dll,可以查到:

图片[6]-Windows开发值得推荐的分析工具,值得收藏-卡核

是截图中的dll库依赖了debug版本的MSVCP100D.dll,找到该问题库的维护组,让他们重新发布release版本的库即可。

       有的库可能是主程序动态启动的,如果这些动态启动的库启动失败,是不会弹出上面那种明确的提示框的。比如A.dll库是动态启动的,如果该库启动失败,会导致相关业务异常,此时可以使用Process Explorer查看主程序的库加载情况,确定A.dll有没有启动起来:

图片[7]-Windows开发值得推荐的分析工具,值得收藏-卡核

注意打开Process Explorer后,要点击上方工具栏中的View DLLs图标按钮才能查看目标进程加载的dll列表,然后在该列表中查看目标库有没有启动起来。

       假设A.dll没有启动起来,有可能其依赖的库找不到,也可能该库中调用的接口在其依赖的库中找不到,用Dependency Walker直接打开A.dll查看其库依赖的情况即可找到原因。如果库有问题,在其前面会显示红色的警告图标:

图片[8]-Windows开发值得推荐的分析工具,值得收藏-卡核

需要注意的是,如下图的黄色感叹号图标一般是没问题的:

图片[9]-Windows开发值得推荐的分析工具,值得收藏-卡核

 还有就是Dependency Walker打开目标文件后,默认会展开所有库的依赖关系包括很多Windows系统库,我们要通过经验加以辨别,将Windows系统库都折叠起来跳过去,一般都是我们程序业务库的问题。

       最后有一点说明一下,Dependency Walker在win10系统中打开文件时特别慢,有可能是对win10系统的兼容性不好,打开文件时要等待几分钟才能打开。

2.3  剪切板查看工具Clipbrd

       该工具主要用来查看剪切板中包含了哪些剪切板格式的数据,在处理剪切板数据的复制粘贴时很有用!       

       在实现IM软件的剪切板复制和粘贴功能时,要支持多种剪切板的格式,要支持与其他常用软件比如QQ、飞秋等间的复制粘贴互通,即在IM软件的聊天框中对图片与文字的混合内容进行复制,可以将内容粘贴到QQ的输入框中,从QQ中复制图片和文字的混合内容,也要能够粘贴到我们的IM软件中。

       那如何知道QQ等软件都支持哪些剪切板格式呢?我们可以先在QQ中复制图片和文字的混合内容,然后打开Clipbrd剪切板查看工具,就可以看到QQ在复制图片和文字的混合内容时都生成了哪些剪切板格式的数据,如下图所示:

图片[10]-Windows开发值得推荐的分析工具,值得收藏-卡核

从图片中可以看出,QQ生成了多种剪切板格式的数据,其中QQ_Unicode_RichEdit_Format格式是QQ专有的格式, HTML Format格式则是通用的格式,是很多软件和邮箱都支持的格式。

        我们可以编写类似如下的测试代码:

		HANDLE hClip = NULL;
		char *pBuf = NULL;
		WCHAR* pwchBuf = NULL;
		char* pTemp = NULL;
		m_dwClipFormatQQ = ::RegisterClipboardFormat( _T("QQ_Unicode_RichEdit_Format") );

		BOOL bRet = ::OpenClipboard( NULL );
		if ( !bRet )
		{
			return;
		}

		hClip = GetClipboardData( m_dwClipFormatQQ );
		if ( NULL == hClip )
		{
			CloseClipboard();
			return;
		}

		pBuf = (char*)GlobalLock( hClip );
		if ( NULL == pBuf )
		{
			GlobalUnlock( hClip );
			CloseClipboard();
			return; 
		}

		int nNum = MultiByteToWideChar( CP_UTF8, 0, pBuf, -1, NULL, 0 );
		pwchBuf = new WCHAR[nNum];
		MultiByteToWideChar( CP_UTF8, 0, pBuf, -1, pwchBuf, nNum );

		CString strContent;
		CopyUtf8ToCStringT( strContent, pBuf );
		m_editContent.SetWindowText( strContent );

		GlobalUnlock( hClip );

可以将指定格式的剪切板数据读出来,看看里面的数据具体是什么样式的内容。比如获取到的QQ_Unicode_RichEdit_Format剪切板格式的数据内容如下

<QQRichEditFormat>
<Info version="1001">
</Info>
<EditElement type="1" filepath="C:\Users\Administrator\AppData\Roaming\Tencent\Users\7100****\QQ\WinTemp\RichOle\MJR{P}JK{HS{077`IF_@$Y3.png" shortcut="">
</EditElement>
<EditElement type="0"><![CDATA[123]]>
</EditElement>
<EditElement type="1" filepath="C:\Users\Administrator\AppData\Roaming\Tencent\Users\7100****\QQ\WinTemp\RichOle\L2_QM_EY}G3)R`76P9HYLPJ.png" shortcut="">
</EditElement>
</QQRichEditFormat>

获取到的HTML Format剪切板格式数据内容如下

Version:0.9
StartHTML:00000112
EndHTML:00000461
StartFragment:00000126
EndFragment:00000425
<!doctype html><html><body>
<!--StartFragment --><DIV>
<IMG src="file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\710027094\QQ\WinTemp\RichOle\LVF%BQDXAUX@0MP2{(%$LLK.png" >123<IMG src="file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\710027094\QQ\WinTemp\RichOle\V8E90K]C]N%1G]8_Q(B48}8.png" >
</DIV><!--EndFragment-->
</body>
</html>

我们可以参考这些剪切板格式的数据样式,就能和这些软件互通了。

       要支持从其他软件中复制内容粘贴到我们的软件中,我们只需要解析通用的HTML Format剪切板格式数据就可以了;要支持从我们软件复制粘贴到其他软件中,我们需要构建通用的HTML Format剪切板格式数据,还要构建粘贴到目标软件时目标软件支持的格式,比如要将复制的内容粘贴到QQ中,则在复制内容时要构造QQ专用的QQ_Unicode_RichEdit_Format剪切板格式,只够造HTML Format剪切板格式,是没法粘贴到QQ中的。飞秋、邮箱等软件都是支持通用的HTML Format剪切板格式的。

2.4  GDI对象查看工具GDIView

       该工具可以查看目标进程的各种GDI对象的占用情况:

图片[11]-Windows开发值得推荐的分析工具,值得收藏-卡核

在处理GDI对象泄露问题时,非常好用。特别是在程序拷机时,可能在UI绘制时,有GDI对象泄露的问题,随着软件的长时间运行,占用的GDI对象可能越来越多,甚至会到达10000个,导致程序卡死或者崩溃。

       在Windows系统中,一个进程占用的GDI绘图对象不允许超过10000个,当接近或超过10000时程序绘图就会出现异常,甚至出现崩溃闪退的问题。

       当程序绘图出现异常或者崩溃时,可以先在Windows系统自带的任务管理器中查看目标进程的GDI对象总个数:

图片[12]-Windows开发值得推荐的分析工具,值得收藏-卡核

如果GDI对象数接近或者达到10000个,则说明程序中肯定有GDI对象泄露了。然后再使用GDIView工具去查看哪些GDI对象在持续增长,没有释放,这样在排查代码时就比较有针对性了,就能很快定位问题了。

       举一个简单的内存泄露的例子,如下所示:

	HPEN hPen2 = ::CreatePen( PS_SOLID, 5, RGB(255,0,0));
	HBRUSH hBr = ::CreateSolidBrush( RGB(0, 255, 0) );
	::SelectObject( hMemDC, hBr );
	HPEN hOldPen = (HPEN)::SelectObject( hMemDC, hPen2 );
	::Rectangle( hMemDC, 0, 0, 20, 20 );
	::SelectObject(hMemDC, hOldPen);

代码中创建了一个pen对象和一个brush对象,结果在这两个对象使用完毕后没有将这两对象给delete掉,这样就导致了GDI对象的泄露。如果上述代码在程序运行的过程中被频繁的执行,则pen对象和brush对象会持续的增长,使用GDIView工具就能看到具体的GDI对象的数目。

       以前帮公司webrtc开发维护小组排查过一个DC对象内存泄露的例子,在他们的代码中调用GetDC去获取窗口的DC,结果在使用完成后没有调用ReleaseDC将DC对象释放掉,就导致了DC对象的泄露,导致他们的程序在运行一段时候后程序的窗口显示异常,然后程序就发生了崩溃。

2.5  Process Explorer

       使用该工具可以查看目标进程的库占用情况,是我们使用很频繁的一个工具!注意第一次启动该工具时,需要点击工具栏中的“View DLLs”图标按钮,才会显示目标进程都加载了哪些库。

图片[13]-Windows开发值得推荐的分析工具,值得收藏-卡核

在进程列表中,点击选择目标进程,下方就会显示加载了哪些库,可以查看这些库的信息,比如占用库的路径,占用库的版本,目标dll库有没有启动起来(加载到进程空间中)等。

       除了查看依赖的dll库信息,还可以查看目标进程中的所有线程信息,比如线程的CPU占用情况,双击线程条目还可以查看线程的实时函数调用堆栈。

       还可以在GPU Graph标签页中查看目标进程是否使用了CPU的GPU硬件单元。在此处简单说一下GPU相关的内容。在很多视频会议、视频监控的软件中,可能会使用CPU的GPU单元,进行视频的硬编硬解,从而节省对CPU的消耗(视频的编解码操作会消耗大量的CPU,即占用大量的CPU百分比)。如果直接使用CPU的计算能力进行的编解码操作,都是软编软解,使用到GPU才是硬编硬解,GPU有很强的硬件运算能力,使用GPU可以有效节省对CPU的软件计算负担。

        在排查CPU占用高的问题时,可以找出哪个线程占用了较高的CPU:

图片[14]-Windows开发值得推荐的分析工具,值得收藏-卡核

 然后双击那个线程的条目,可以查看到该线程中当前的函数调用堆栈:

图片[15]-Windows开发值得推荐的分析工具,值得收藏-卡核

通过函数调用堆栈,我们可能就能大概确定是哪个业务线程导致的高CPU占用了,就可以有针对性地排查了。必要时,可能还要借助windbg作进一步分析,查看详细的函数调用堆栈信息,查看函数中变量的值等。

2.6  Prcoess Monitor

       使用该工具可以监测目标进程对注册表和文件的操作:

图片[16]-Windows开发值得推荐的分析工具,值得收藏-卡核

       使用该工具可以监测目标进程的注册表活动,比如想知道目标进程在执行某个操作时将相关信息写到哪个注册表路径中,可以使用该工具对注册表活动进行监测。

       使用该工具可以监测目标进程的文件活动,再比如,测试同事在测试时,会遇到软件生成了一些莫名的日志文件,需要定位到日志是哪个模块生成的,需要将生成日志文件的代码清理掉,此时可以使用该工具对文件活动进行监测。当检测到对目标文件的操作,双击打开当前操作的调用堆栈,通过堆栈的上下文,就可以看出日志文件是哪个模块生成的。另外,在Win7及以上系统中的注册表和文件的重定向问题时,使用该工具可以查看到被重定向到哪个路径中了。

       该工具的具体使用方法先点击工具栏的图片[17]-Windows开发值得推荐的分析工具,值得收藏-卡核漏斗按钮,添加要监测的目标进程

图片[18]-Windows开发值得推荐的分析工具,值得收藏-卡核

 然后在工具栏将不需要监测的活动类型取消掉:(一般我们只监测文件活动和注册表活动)

图片[19]-Windows开发值得推荐的分析工具,值得收藏-卡核

2.7  API Monitor

       该工具可以来窥探其他软件在实现一些功能时都调用了哪些系统API:

图片[20]-Windows开发值得推荐的分析工具,值得收藏-卡核

 估计出这些功能的实现方法,还可以查看到调用API时都传递了什么样的参数,尝试解决我们软件在开发时遇到的问题。       

       比如在处理我们安装包的管理员权限问题、64位系统中的桌面快捷方式问题时,都是通过该工具对某主流软件的安装包的监测,帮我们找到了解决问题的办法。

       再比如在实现文件传输的打开文件所在文件夹功能时,使用了该工具对某主流软件和迅雷进行监测,找到了解决问题的办法,甚至还发现了迅雷的一个掩藏很深的bug。

       还有一个实例,我们软件在打开chm文件时遇到了一些问题,使用该工具监测了Beyond compare软件,该软件有操作.chm文件的功能,获得了Beyond compare软件在调用对应的API函数时传递的参数

       此外,该工具除了可以监测对系统API的调用,还可以监测对第三方库的导出函数的调用。

       该工具的具体使用方法以监控某安装包程序为例,先将目标监控程序启动起来,在左侧的函数列表中搜索要监控的API,比如ShellExecute和CreateProcess,将搜索到目标函数都勾选上

图片[21]-Windows开发值得推荐的分析工具,值得收藏-卡核

然后再左下侧的进程列表中,选择要监控的进程,点击右键菜单中的“Start Monitoring”即可开启监控。然后让目标监控程序继续跑下去,这样就能监控到目标API函数的调用情况了:

图片[22]-Windows开发值得推荐的分析工具,值得收藏-卡核

2.8  调试器Windbg 

       Windbg是windows系统强大的调试器,在解决软件异常崩溃时非常有用,是我们用的最多的一款工具!

图片[23]-Windows开发值得推荐的分析工具,值得收藏-卡核

       我们可以静态分析一异常发生时捕获到的dump文件,也可以将Windbg动态地挂载到目标进程中进行调试。比如遇到死循环时,可以采用动调试的方法,在Windbg中设置代码断点,可以确定到底死循环发生在哪个函数中。

       Windbg排查异常问题时,其效率比我们直接去排查代码要高很多。Windbg的入门也相对简单,只需要掌握常用的命令,了解函数调用的栈分布图,知晓函数调用的栈回溯原理,但如果要深入分析,就需要有较深的软件开发经验和汇编语言基础了。

       后面会有专门的文章重点介绍Windbg,在此就不再赘述了。

2.9  反汇编工具IDA 

       IDA是交互式反汇编工具,可以直接打开exe或者dll等二进制文件,查看文件中的汇编代码:

图片[24]-Windows开发值得推荐的分析工具,值得收藏-卡核

       平时我们主要是是来辅助Windbg去分析和排查软件异常问题的。Windbg中也能直接查看到汇编代码,但是经过编译器优化的汇编代码很难和C++源代码对应起来,在有pdb的情况下,使用IDA查看汇编代码就方便多了,能很好的和C++源代码对应起来。有时要搞清楚代码奔溃的本质,还是要分析具体的汇编代码的。

         后面会有专门的文章重点介绍IDA反汇编工具,在此就不再赘述了。

2.10  抓包工具Wireshark

       WireShark是网络抓包软件,是分析网络问题的必备神器,是我们日常开发工作中用的最多的工具之一!

图片[25]-Windows开发值得推荐的分析工具,值得收藏-卡核

       它可以抓取主机网卡上发出和接收的网络数据包,常用来分析各种网络异常问题,比如接收和发送的网络数据是否有有异常、网络通信的双方有没有正常完成相关流程的交互等。

       这个软件非常的常用,做IT的人应该都用过,网上一堆使用教程,在此就不再赘述了!

3、总结

       作为Windows开发人员,是和很有必要了解和掌握上述工具的使用的。本文结合实际应用场景,对这些工具作了简单的介绍,希望能给相关人员提供一些借鉴或参考。

       此外,上述工具在运行时可能需要管理员权限,所以启动时最好选择右键以管理员方式启动。

快来围观吧!图片[26]-Windows开发值得推荐的分析工具,值得收藏-卡核有想法和建议,可以在评论区留言!

Windbg等工具的下载链接如下:

链接:https://pan.baidu.com/s/1ID6_0RSYKbiy_tzfYDX3Ew 
提取码:tn6i

© 版权声明
THE END
喜欢就支持一下吧
点赞1.8W+赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容