ShellExecuteEX张开iqy文件导致excel hang的原故分析

1. 问题

try
{
fs = new StreamReader(new FileStream(path, FileMode.Open,
FileAccess.Read),
Encoding.GetEncoding(“gb2312”));//符合规律读取文件,倘若被excel程序独占的话,此时会抛出非常
}
catch(Exception e)
{
//抛出十二分后,那么即可拷贝此文件到有时文件夹下生成的一个即兴文件中,然后读取此有的时候文件就可以
string tempFile = Path.GetTempPath() + Path.GetRandomFileName();
File.Copy(path, tempFile);
fs = new StreamReader(new FileStream(tempFile, FileMode.Open,
FileAccess.Read), Encoding.GetEncoding(“gb2312”));
}

当在console中调用API
ShellExecuteEx打开”test.iqy”文件时,发掘excel会hang住,console退出后excel才会响应,但一贯双击”test.iqy”是未有毛病的,有趣的是那个状态独有在xp产生,在win7上从不那几个标题。

 

2. 复发步骤

重现境况:XP sp3 / Office 二零零六(别的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 = { 0 };
    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住的地方

图片 1

能够观望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的调用,果然搜到一条

图片 2

call stack显示的确是ShellExecuteEx所调用

图片 3

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

专一到下三个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70
),刚好是赢得那几个窗口的pid和tid,查看下参数窗口:

那个窗口所属的长河PID =
0xc54,正好是excel的进程,表达ShellExecuteEx确实发送了DDE新闻给excel,况且可执发送的音信的thread便是主线程

图片 4

基于DDE的消息参数,可见wParam正是出殡和下葬音讯的窗口,其句柄为2425190 =
0x250166,反向查询知那是ShellExecuteEx创设的”WorkerW”窗口

图片 5

图片 6

 

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

图片 7

翻看一下buff的地方:

图片 8

刚好正是开垦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

图片 9

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

图片 10

能够是ShellExecuteEx内部创立的线程,所以win7上ShellExecuteEx创立了五个线程特地用来拍卖和excel的DDE音讯通讯,那样就能够健康的吸收接纳管理excel发过来的WM_DDE_INITIATE消息了

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图