大发体育娱乐在线-大发体育娱乐官方网站-大发体育娱乐登录网址
做最好的网站

Windows消息机制要点,hang的原因分析

来源:http://www.dfwstonefabricators.com 作者:操作系统 人气:127 发布时间:2019-09-22
摘要:1. 问题 1. 窗口进程   种种窗口会有二个称作窗口过程的回调函数(WndProc),它含有多少个参数,分别为:窗口句柄(WindowHandle),音讯ID(Message ID),和多少个新闻参数(wParam,lParam),当窗口收到新

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, LOWO凯雷德D(wParam)表示菜单项,工具栏开关或控件的ID。假如是控件, HIWOTiggoD(wParam)表示控件新闻类型
3> 控件布告(Notify Message) 
控件公告新闻, 那是最灵敏的音信格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHDTucson的指针。NMHD揽胜极光包蕴控件通告的内容, 能够随心所欲扩充。
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_TIME奇骏唯有在Queue中并未有别的音讯的时候才会被拍卖,WM_PAINT音信还有大概会被合併以进步功效。其余具有消息以先进先出(FIFO)的点子被管理。

2. 复发步骤

4 队列消息(Queued Messages)和非队列音讯(Non-Queued Messages)
1)队列新闻(Queued Messages)
 
音信会先保存在消息队列中,信息循环会从此队列中取音信并散发到各窗口管理
如鼠标,键盘新闻。
2) 非队列新闻(NonQueued Messages) 新闻会绕过系统音信队列和线程新闻队列直接发送到窗口进程被拍卖
如: WM_ACTIVATE, WM_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住的地点

图片 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的调用,果然搜到一条

图片 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消息了

本文由大发体育娱乐在线发布于操作系统,转载请注明出处:Windows消息机制要点,hang的原因分析

关键词:

最火资讯