ShellExecuteEX打开iqy文件导致excel,Windows消息机制要点

1. 问题

1. 窗口进度 
各类窗口会有一个称得上窗口进度的回调函数(WndProc),它饱含七个参数,分别为:窗口句柄(Window
Handle),音信ID(Message ID),和多个新闻参数(wParam,
lParam),当窗口收到音信时系统就能够调用此窗口进度来处理音讯。(所以叫回调函数)

当在console中调用API
ShellExecuteEx打开”test.iqy”文件时,开掘excel会hang住,console退出后excel才会响应,但一直双击”test.iqy”是绝非难点的,风趣的是以此景况唯有在xp发生,在win7上未曾那几个主题材料。

2 音讯类型 
1) 系统定义信息(System-Defined Messages)
 
在SDK中优先定义好的新闻,非客商定义的,其范围在[0x0000, 0x03ff]以内,
能够分为以下三类:
1>窗口新闻(Windows Message) 
与窗口的内部运营有关,如创制窗口,绘制窗口,销毁窗口等。可以是平日的窗口,也足以是Dialog,控件等。
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL…
2>命令音讯(Command Message):注意那类音讯通称为WM_COMMAND
与拍卖客商供给有关, 如单击菜单项或工具栏或控件时, 就能够发生命令音信。
WM_COMMAND, LOWOOdysseyD(wParam)表示菜单项,工具栏按键或控件的ID。假诺是控件,
HIWO奔驰G级D(wParam)表示控件音信类型
3> 控件布告(Notify Message) 
控件布告音信, 这是最灵敏的消息格式, 其Message, wParam,
lParam分别为:WM_NOTIFY,
控件ID,指向NMHDENCORE的指针。NMHD景逸SUV包涵控件公告的原委, 能够Infiniti制扩展。
2) 程序定义音讯(Application-Defined Messages) 
顾客自定义的消息, 对于其范围有如下规定:
WM_USER: 0x0400-0x7FFF    (ex. WM_USER+10)
WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF

 

3 音信队列(Message Queues) 
Windows中有两体系型的音讯队列
1) 系统音讯队列(System Message Queue) 那是三个体系唯一的Queue,设备驱动(mouse,
keyboard)会把操作输入转化成音信存在系统队列中,然后系统会把此消息放到指标窗口所在的线程的音信队列(thread-specific
message queue)中伺机处理
2) 线程消息队列(Thread-specific Message Queue) 每三个GUI线程都会爱慕这么二个线程音信队列。(那个行列独有在线程调用GDI函数时才会创制,暗许不成立)。然后线程音信队列中的音信会被送到对应的窗口进度(WndProc)管理.
注意:
线程音讯队列中WM_PAINT,WM_TIMELX570独有在Queue中并未有任何音讯的时候才会被管理,WM_PAINT音讯还有只怕会被联合以升高功能。其余兼具音讯以先进先出(FIFO)的法子被拍卖。

2. 复出步骤

4 队列新闻(Queued Messages)和非队列消息(Non-Queued Messages)
1)队列音讯(Queued Messages)
 
消息会先保存在新闻队列中,音讯循环会从此队列中取新闻并散发到各窗口管理
如鼠标,键盘音讯。
2) 非队列音讯(NonQueued Messages) 音信会绕过系统消息队列和线程新闻队列直接发送到窗口进度被管理
如: WM_ACTIVATE, WM_永利澳门游戏网址304,SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED 
只顾: postMessage发送的音信是队列新闻,它会把音讯Post到音信队列中;
SendMessage发送的音讯是非队列音讯, 被一贯送到窗口进程管理

复发景况:XP sp3 / Office 二零零六(别的office版本应该也足以,未有测量试验)

5 PostMessage(PostThreadMessage), SendMessage 
PostMessage:把音信放到内定窗口所在的线程音信队列中后旋即赶回。
PostThreadMessage:把信息放到内定线程的消息队列中后立马回到。
SendMessage:直接把消息送到窗口进程处理,管理完了才回到。

6 GetMessage, PeekMessage 
PeekMessage会即刻赶回能够保存新闻
GetMessage在有音信时重回会删除新闻

1> 解压iqy_test.zip

7 TranslateMessage, TranslateAccelerator 
TranslateMessage: 把三个virtual-key音讯转化成字符音信(character
message),并放置当前线程的音信队列中,消息循环下二回收取管理。
TranslateAccelerator:将快捷键对应到对应的美食指南命令。它会把WM_KEYDOWN 或
WM_SYSKEYDOWN转化成连忙键表中相应的WM_COMMAND或WM_SYSCOMMAND新闻,
然后把转化后的 WM_COMMAND或WM_SYSCOMMAND间接发送到窗口进度管理,
管理完后才会回来。

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

8(音信死锁( Message Deadlocks) 
一旦有线程A和B, 今后有以下下步骤
1) 线程A SendMessage给线程B, A等待音讯在线程B中拍卖后重回
2) 线程B收到了线程A发来的新闻,并进行拍卖, 在管理进度中,B也向线程A
SendMessgae,然后等待从A重回。
因为那时, 线程A正等待从线程B重回, 不可能管理B发来的音讯,
从而导致了/线程A,B互相等待, 变成死锁。多少个线程也能够产生环形死锁。
能够采用 SendNotifyMessage或SendMessageTimeout来制止出现死锁。

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

9 BroadcastSystemMessage 
咱俩日常所接触到的音讯都以发送给窗口的,其实,
信息的接收者能够是精彩纷呈的,它能够是应用程序(applications),
可安装驱动(installable drivers),网络设施(network drivers),
系统级设备驱动(system-level device drivers)等, 
布罗兹castSystemMessage这几个API能够对上述系统组件发送音讯。

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 %pn", shell_exec_info.hProcess);

    return ret;
}

 

3. 原因解析

3.1 excel hang在哪里?

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

永利澳门游戏网址304 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

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

永利澳门游戏网址304 2

call stack展现的确是ShellExecuteEx所调用

永利澳门游戏网址304 3

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

发表评论

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