是否可以获取调用SetWindowPos的来源?

时间:2019-01-10 14:13:17

标签: winapi

我们遇到了一个有关应用程序“冻结”的问题。经过调查,结果是,我们的主表单最终以WS_EX_TOPMOST结尾,因此,当显示出一个模态表单时,它最终被显示在我们的主表单之后,然后似乎被冻结了。

考虑到我们从未将表格设置为TOPMOST,目前的工作假设是通过以下方式将另一个应用程序错误地或不正确地将应用程序的主表格设置为TOPMOST:

SetWindowPos(OurFormHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE)

那么如何识别有罪的一方?

我将发布我想出的方法,只是想知道是否还有更可靠的方法...

1 个答案:

答案 0 :(得分:0)

据我所知,对SetWindowPos的调用直到拥有目标窗口的进程WM_WindowPosChangingWM_WindowPosChanged消息的进程才返回。

在WM_WindowPosChanging期间,似乎无法知道该表单是否将成为最顶层,更不可能阻止它(hwndInsertAfter不再是HWND_TOPMOST了,甚至都没有引用TOPMOST窗口)。因此,我们在这里无能为力,因为我们不知道自己是否遇到麻烦。

但是,当处理WM_WindowPosChanged时,WS_EX_TOPMOST样式已应用于窗口的样式。因此,到那时,您知道自己已设置为最高。

所以现在...我们如何才能使“有罪程序”在人群中脱颖而出?好吧,我确实提到SetWindowPos直到WM_WindowPosChanged完成处理后才返回。因此,如果我们在处理WM_WindowPosChanged时要睡眠10秒钟,则调用过程将变得无响应!

到那时,我们可以EnumWindows并测试它们是否为IsHungAppWindow,并检索它们所属的应用程序的名称。

哦...,我们仍然会收集一个调用栈,以防万一这实际上是我们代码中某些狂放的副作用而不是“恶意应用程序”的结果。

限制

很显然,如果从无窗口线程中调用SetWindowPos,该技术将无法正常工作。它也可能有一些误报。

其中一些很可能是通过“实现”而不是“通过设计”来实现的。