我们多次在项目中使用API Monitor工具监测参考程序对系统API函数的调用,找到问题的解决办法,API Monitor工具确实很好用,今天我们就来详细介绍一下如何使用API Monitor工具。
1、问题背景
我们以之前一个项目问题为例。在某些场景下,Windows系统因为鼠标没操作出发自动关闭显示器、自动屏保、自动待机等会打断我们正在进行的事务。比如我们当前正在使用会议软件开会,如果系统自动关闭了显示器或者待机,就会打断正在进行中的会议(看不到视频等),用户体验也是非常差的,所以我们要在进入开会状态后,阻止系统屏保,阻止子系统自动关闭屏幕,阻止系统自动待机。
以阻止屏保为例,我们在网上搜索得知,可以调用系统API函数SystemParametersInfo主动关闭屏保,但调用该函数应该使用哪些具体的函数参数,以及使用该函数是否能实现既定的功能,一开始是不得而知的。所以我们想使用API Monitor工具去监控一下一款主流的会议软件,看看该软件是不是调用SystemParametersInfo接口去组织屏保的,以及调用该接口都使用了哪些参数。
2、使用API Monitor工具监测目标软件对SystemParametersInfo接口的调用
启动API Monitor后,先在左边的API函数列表中搜索到SystemParametersInfo函数,勾选上;然后在进程列表中找到目标进程,右键单击目标进程,在弹出的右键菜单中点击Start Monitoring,启动监测,操作步骤如下图所示:
但在进程列表中该参考软件有多个进程(通过进程名称和图标可以看出),不知道哪个是与会议相关的进程。这些进程都要监控,有两个办法。一个是按照上图操作将多个进程一个一个添加到监控列表中,二是在通过API Monitor中点击“Monitor New Process”按钮去启动参考软件:
这样API Monitor就可以监控该参考软件启动的所有进程了。
但好像有时即使通过“Monitor New Process”按钮启动软件,也不会把启动程序的所有进程加入到监控列表中,所以还是需要手动添加到监控进程列表中的。
于是使用参考软件创建一个会议,加入到会议中,然后在监测的进程列表中,切换点击该参考软件的多个进程,看看哪个进程调用SystemParametersInfo函数时传入了SPI_SETSCREENSAVEACTIVE参数,可以按下Ctrl+F快捷键调出搜索窗口,在监测结果中以SPI_SETSCREENSAVEACTIVE为关键字进行搜索,果然监测到了,如下:
- 上图中有监控进程列表,有多个进程时需要切换查看。
- 点击监测结果列表中的某行记录,下方callstack子窗口中会显示该行记录对应的函数调用堆栈的(只显示4帧)。
我们单独对监测结果列表截图,可以看的更清楚一点:
在退出会议时,可以监测到又调用了SystemParametersInfo函数(第一个参数传SPI_SETSCREENSAVEACTIVE,第二个参数传TRUE(1),TRUE即表示开启屏保),恢复系统的屏保,如下:
3、到MSDN上查看SystemParametersInfo API函数的说明,查看到关键参数的含义
API Monitor工具开启监测后不仅看到调用了什么API函数禁用屏保,还能看到调用该API函数时传递了什么参数。参考软件的实际运行效果是,入会时禁用屏保仅仅是作用于当前登录的会话,不会保存到系统全局配置里面去的,所以系统重启后读取系统全局配置,系统全局配置中是启用屏保的。
那我们回过头来看这个API函数在MSDN上的说明,对比API Monitor中调用SystemParametersInfo函数设置的参数,看看是否有不写入系统全局配置文件的参数。
对于Windows C++软件开发人员来说,到微软MSDN上查看API接口等的详细说明,是必须要掌握的基础技能!
SystemParametersInfo的fWinIni参数,从参数名称上看好像是和Windows系统配置文件有关,于是查看该参数的说明:
说明中指出,此字段决定是否写入到系统user profile中。从API Monitor监测到参考软件调用SystemParametersInfo时给fWinIni参数设置的值为0,综合参考软件的实际表现,所以确定fWinIni字段就是设置是否写入到系统全局配置文件中的。
MSDN上对SystemParametersInfo函数的最后一个参数fWinIni的说明不够清晰,比较隐晦,我们没搞清楚其对应的真实含义,通过这次问题我们才结合实际现象才搞懂该参数的真实用途。
参考软件在加入会议时调用SystemParametersInfo禁用屏保,给fWinIni参数设置的值为0,那么此次禁止屏保,仅仅是作用于当前登录的会话,不会保存到系统全局配置里面去的。如果入会后出现崩溃或者强杀进程,没机会恢复屏保,但当前禁用屏保只作用于当前登录的会话,系统重启后系统会从系统配置文件中读取到屏保启用的配置项,系统还是能继续屏保的。所以我们软件也可以这样处理的。
入会时调用SystemParametersInfo函数,传入SPI_GETSCREENSAVEACTIVE,获取系统有没有设置屏保,如果设置了屏保,就再调用SystemParametersInfo函数,传入SPI_SETSCREENSAVEACTIVE和FALSE参数,临时取消系统屏保,代码如下:
// 先获取是否启用屏幕保护
SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_bScreenSaveActive, 0);
if (m_bScreenSaveActive)
{
// 阻止屏保
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
}
退会时,如果之前取消了屏保,则再调用SystemParametersInfo函数,传入SPI_SETSCREENSAVEACTIVE和TRUE参数,恢复系统屏保,代码如下:
if (m_bScreenSaveActive)
{
// 取消阻止屏保
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, NULL, 0);
}
4、最后
本文通过一个问题实例详细地说明了API Monitor工具的使用,给大家提供一个借鉴或参考。我们已经使用API Monitor工具解决了项目开发过程中遇到的多个问题,没用过的朋友可以尝试着用一下。
对于本文中讲的问题实例,更详细的内容可以参见我之前写的一篇文章:
VC++实现会议中阻止屏保、阻止系统自动关闭屏幕、阻止系统待机(附源码)https://blog.csdn.net/chenlycly/article/details/124526549
版权归原作者 dvlinker 所有, 如有侵权,请联系我们删除。