Возможно ли получить происхождение вызова SetWindowPos? - PullRequest
0 голосов
/ 10 января 2019

Нам сообщили о проблеме с зависанием нашего приложения. После исследования происходит то, что наша основная форма заканчивается WS_EX_TOPMOST, поэтому, когда отображается модальная форма, она оказывается за нашей основной формой, которая затем кажется замороженной.

Учитывая, что мы никогда не устанавливали нашу форму как TOPMOST, наше рабочее предположение на данный момент состоит в том, что другое приложение, по ошибке или нет, устанавливает основную форму нашего приложения как TOPMOST через:

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

Так как же определить виновного?

Я выложу метод, который придумал, просто интересно, есть ли что-нибудь более надежное ...

1 Ответ

0 голосов
/ 10 января 2019

Из того, что я могу сказать, вызов SetWindowPos не возвращается до тех пор, пока процесс, владеющий процессом целевого окна, не отправит сообщение WM_WindowPosChanging и WM_WindowPosChanged.

Во время WM_WindowPosChanging не представляется возможным узнать, станет ли форма самой верхней, тем более предотвратить ее (hwndInsertAfter больше не является HWND_TOPMOST и даже не ссылается на окно TOPMOST). Так что мы мало что можем сделать здесь, так как не знаем, попадаем ли мы в беду.

Однако при обработке WM_WindowPosChanged стиль WS_EX_TOPMOST был применен к стилю окна. Таким образом, к этому моменту вы знаете, что вы были наивысшим.

Так что теперь ... Как мы можем заставить "процесс обвинения" выделиться из толпы? Ну, я упоминал, что SetWindowPos не возвращается, пока WM_WindowPosChanged не завершит обработку. Так что, если бы мы, скажем, поспали 10 секунд во время обработки WM_WindowPosChanged, вызывающий процесс стал бы не отвечающим!

В этот момент мы можем EnumWindows и проверить, являются ли они IsHungAppWindow, и получить названия приложений, которым они принадлежат.

Ох ... и мы все равно будем собирать стек вызовов, если это на самом деле результат какого-то дикого побочного эффекта в нашем коде, а не "мошенническое приложение".

Ограничения

Очевидно, что если SetWindowPos вызывается из потока без окон, эта техника не будет работать. Это может также иметь несколько ложных срабатываний.

Часть этого, скорее всего, работает "по реализации", а не "по замыслу".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...