1. 问题

当在console中调用API ShellExecuteEx打开"test.iqy"文件时,发现excel会hang住,console退出后excel才会响应,但直接双击"test.iqy"是没有问题的,有意思的是这个情况只有在xp发生,在win7上没有这个问题。

2. 重现步骤

重现环境:XP sp3 / Office 2007(其他office版本应该也可以,没有测试)

https://files.cnblogs.com/files/organic/iqy_test.zip

1> 解压iqy_test.zip

2> 运行http_server.py(需先安装python)

3> 执行"shell_execute.exe test.iqy"

shell_execute.exe的主要code:

bool shell_execute_file(wstring file_path)
{
SHELLEXECUTEINFOW shell_exec_info = { };
shell_exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
shell_exec_info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
shell_exec_info.hwnd = NULL;
shell_exec_info.lpVerb = NULL;
shell_exec_info.lpFile = file_path.c_str();
shell_exec_info.lpParameters = NULL;
shell_exec_info.lpDirectory = NULL;
shell_exec_info.nShow = SW_SHOW;
shell_exec_info.hInstApp = NULL;
bool ret = ShellExecuteExW(&shell_exec_info);
printf("process handle is %p\n", shell_exec_info.hProcess); return ret;
}

3. 原因分析

3.1 excel hang在哪里?

3.1.1 用windbg附加到excel上,输入如下命令查看主线程hang住的地方

可以看到Excel hang在NtUserMessageCall()中,经过查询知,SendMessage()内部就是调用NtUserMessageCall()来发送消息的。

查看参数知excel调用NtUserMessageCall()类似如下:

NtUserMessageCall(HWND_BROADCAST, WM_DDE_INITIATE)

说明excel给所有顶层窗口发送一个WM_DDE_INITIATE消息,但是有窗口没有response

由此可以怀疑是由于console进程在和excel用DDE消息通信时,console没有响应excel发送的DDE消息,导致excel hang住

3.2 为了验证3.1.1的猜想,用API Monitor一下ShellExecuteEx

3.2.1 根据微软的文档可知,发送DDE消息除了WM_DDE_INITIATE和WM_DDE_ACK之外用的都是PostMessage

https://msdn.microsoft.com/en-us/library/windows/desktop/ff468829(v=vs.85).aspx

在API Monitor中搜索一下PostMessage的调用,果然搜到一条

call stack显示确实是ShellExecuteEx所调用

消息1000为WM_DDE_EXECUTE,Post窗口句柄为0x00310172。

注意到下一个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70 ),刚好是获取这个窗口的pid和tid,查看下参数窗口:

这个窗口所属的进程PID = 0xc54,正好是excel的进程,说明ShellExecuteEx确实发送了DDE消息给excel,而且可执发送的消息的thread就是主线程

根据DDE的消息参数,可知wParam就是发送消息的窗口,其句柄为2425190 = 0x250166,反向查询知这是ShellExecuteEx创建的”WorkerW”窗口

3.2.2 为了验证3.2.1的结论,在PostMessageW上下断点跟踪一下

查看一下buff的地址:

刚好就是打开test.iqy的命令,说明ShellExecuteEx就是先创建了excel的进程,然后发送test.iqy的文件命令给excel打开。

3.3 总结

1> ShellExecuteEx打开test.iqy的时先创建excel进程

2> 然后创建一个"WorkerW"的窗口用于DDE通信

3> Post WM_DDE_EXECUTE给excel,告知打开test.iqy的命令

4> ShellExecuteEx执行结束,但并不destroy "WorkerW"窗口

5> excel收到WM_DDE_EXECUTE消息后会广播WM_DDE_INITIATE消息,"WorkerW"窗口所在的console进程由于没有定义消息处理函数,ShellExecuteEx定义的"WorkerW"窗口消息处理函数得不到CPU执行机会,导致不会response该消息,从而导致excel hang住

类似,我们可以创建一个带窗口的程序,启动后将其挂起,这时,即使直接双击打开test.iqy也会hang住。

4. 为什么双击打开excel不会hang住

因为双击打开实际是用explorer.exe打开,而explorer.exe是有窗口的,能够正常的接收处理WM_DDE_INITIATE消息

5. 为什么win7上不会有这样的问题

5.1 在API Monitor中看下PostMessageW

注意到win7下PostMessageW是用的线程2调用的,搜一下线程创建API CreateThread

可知是ShellExecuteEx内部创建的线程,所以win7上ShellExecuteEx创建了一个线程专门用来处理和excel的DDE消息通信,这样就能正常的接收处理excel发过来的WM_DDE_INITIATE消息了

ShellExecuteEX打开iqy文件导致excel hang的原因分析的更多相关文章

  1. 连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法

    本文出处:http://www.cnblogs.com/wy123/p/6110349.html 之前遇到过这么一种情况: 连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持 ...

  2. Pycharm下同一目录的py文件不能相互调用的原因分析

    1.首先确保所在目录是Python Package而不是一般的New Stratch File Python Package下有__init___.py或自己建空的__init___.py 2.pyc ...

  3. mips64高精度时钟引起ktime_get时间不准,导致饿狗故障原因分析【转】

    转自:http://blog.csdn.net/chenyu105/article/details/7720162 重点关注关中断的情况.临时做了一个版本,在CPU 0上监控所有非0 CPU的时钟中断 ...

  4. ArcSOC进程数不断增长导致oracle processes溢出原因分析

    现场出现了一个问题,oracle运行一段时间之后,process个数会溢出,然后新的连接会失败.通过分析,发现Arcgis Server 的ArcSOC进程在不段增长.ArcSOC是arcgis se ...

  5. Python导出DBF文件到Excel的方法

    Python导出DBF文件到Excel的方法 这篇文章主要介绍了Python导出DBF文件到Excel的方法,实例分析了Python基于win32com模块实现文件导出与转换的相关技巧,分享给大家供大 ...

  6. 解决 Mac Pro 用 Excel 打开 CSV 文件不能正常显示的问题

    在做系统后台的时候,往往会有导出系统信息(如,用户信息)功能,一般导出为CSV文件. 先前在 Windows 下,导出的CSV文件用 Excel 打开能正常显示,可现在在 Mac 系统中,显示一团乱, ...

  7. 打开Excel时提示"您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致"

    问题描述:     系统安装了WPS时,Analyzer导出excel时候,会提示"您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致",这是Excel的安全问题,   ...

  8. Excel:您尝试打开的文件的格式与文件扩展名指定的格式不一致

    报错信息: 打开文件时提示"您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致.打开文件前请验证文件没有损坏且来源可信.是否立即打开该文件?",卸载Office 20 ...

  9. excel打开csv文件乱码解决办法

    参考链接: https://jingyan.baidu.com/article/4dc408484776fbc8d846f168.html 问题:用 Excel 打开 csv 文件,确认有乱码的问题. ...

随机推荐

  1. 本人开源项目 Lu-Rpc

    Lu-Rpc 是个专为学习者准备的 RPC 框架, 初始架构非常简单, 可供初学者扩展和学习. Lu 可以认为是中文世界的撸, 即撸 Rpc--- 造个 Rpc 轮子. Lu-Rpc 架构图如下: L ...

  2. [转]mysql优化——show processlist命令详解

    本文转自:https://blog.csdn.net/sunqingzhong44/article/details/70570728 版权声明:本文为博主原创文章,未经博主允许不得转载. https: ...

  3. OpenLiveWriter.exe已停止工作---解决办法

    一.起因 在win10的系统中成功的安装了OpenLiveWriter,但是在家里win7的电脑上装不上.点击 OpenLiveWriterSetup.exe的安装包后出现 OpenLiveWrite ...

  4. 【机器学习】Google机器学习工程的43条最佳实践

    https://blog.csdn.net/ChenVast/article/details/81449509 本文档旨在帮助那些掌握机器学习基础知识的人从Google机器学习的最佳实践中获益.它提供 ...

  5. win10电脑怎么录制视频 电脑录制视频软件

    win10电脑怎么录制视频?相信不少网友正在面临这个疑惑.现如今是网络信息科技时代,快速传播信息的途径和方式有很多种.其中,通过录制电脑视频,可以制作视频教程.游戏解说,还可以录制在线视频存储影视资源 ...

  6. [C语言]易错知识点、小知识点复习(1)

    1. 计算机只能识别由0和1组成的二进制指令,需要将用高级语言(如C.C++)编写的源程序(.c..cpp)编译成二进制目标文件(.obj).一个程序可以根据需要写在不同的文件里,编译是以文件为单位进 ...

  7. MySQL 横向表分区之RANGE分区小结

    MySQL 横向表分区之RANGE分区小结 by:授客 QQ:1033553122 目录 简介 1 RANGE分区 1 创建分区表 1 查看表分区 2 新增表分区 2 新增数据 3 分区表查询 3 删 ...

  8. Android为TV端助力 am命令以及hotkey文件的编写

    1.拨打电话:am start -a android.intent.action.CALL -d tel:10086 这里-a表示动作,-d表述传入的数据,还有-t表示传入的类型. 2. 打开一个网页 ...

  9. Android SurfaceView实现跟随手指移动的光标

    实例 public class DragSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{ priv ...

  10. C#:获取视频某一帧的缩略图

    读取方式:使用ffmpeg读取,所以需要先下载ffmpeg.网上资源有很多. 原理是通过ffmpeg执行一条命令获取视频某一帧的缩略图. 首先,需要获取视频的帧高度和帧宽度,这样获取的缩略图才不会变形 ...