Подтвердить что ты не робот

Как я могу остановить приложение от получения определенного "сообщения"?

ВОЗМОЖНОЕ РЕШЕНИЕ НАЙДЕНО!

Я считаю, что нашел решение! Я буду продолжать тестирование, чтобы убедиться, что он действительно работает, но я надеюсь... Я подробно рассказал, как я нашел решение в EDIT THREE вопроса!

Для тех, кто хочет узнать полный фон по моей проблеме и что я пробовал в результате ввода этого вопроса, см. это: http://pastebin.com/nTrEAkVj

Я буду редактировать это часто ( > 3 раза в день в большинстве будних дней), когда я продвигаю свои исследования и ситуацию, поэтому продолжайте проверять, если вы заинтересованы или имеете некоторую информацию или знания о моей проблеме:)

Краткое описание:

У меня есть это приложение, которое я создал, которое может быть разбито путем изменения моей экранной заставки или блокировки моей рабочей станции, и вообще всякий раз, когда на нее отправляется сообщение WM_WININICHANGE/WM_SETTINGSCHANGE.

Если я могу последовательно разбивать свое приложение, меняя свою заставку, то НЕКОТОРАЯ часть этого - это отправка моего приложения. Некоторое сообщение (не обязательно сообщение Windows, я имею в виду сообщение в самом общем смысле), которое, в свою очередь, катастрофический для моей заявки. Из-за этого я пытаюсь найти способ блокировать любое сообщение, из-за которого моя проблема не обрабатывается моим приложением. Я знаю, что это не лучший способ решить проблему, поэтому вам не нужно говорить мне. Посмотрите на справочную информацию или спросите, почему, если это вас беспокоит (есть веская причина).

Мой вопрос:

есть несколько вещей, которые любая информация о помогла бы мне решить мою проблему, помеченную в соответствии с релевантностью (1 наиболее актуальным, 3 немного менее полезным):

  • Я пытаюсь использовать Wndproc() для фильтрации моего сообщения следующим образом:

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If CInt(m.Msg) <> CInt(26) then
            MyBase.WndProc(m)
        end if
    End Sub
    

    Однако, по словам Windspector, сообщение WM_WININICHANGE по-прежнему отправляется в мое приложение (это имеет смысл), НО оно также возвращается с 0... это не должно происходить, если оно работает правильно, оно должно "Не возвращай ничего, не так ли? Информация о том, почему это не работает, как я ожидал, и как это сделать, было бы чрезвычайно полезно!

  • Я также пробовал использовать фильтры сообщений:

    Public Class MyMessageFilter
        Implements IMessageFilter
        Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
            ' Return true for messages that you want to stop  << someone elses comment       
            Return m.Msg = 26
        End Function
    End Class
    

    а затем добавив мой метод mybase.load:

    Application.AddMessageFilter(New MyMessageFilter())

    однако они, по-видимому, только фильтруют определенные сообщения, и такие сообщения, как мои, не кажутся в них. информация о том, если определенно невозможно использовать какой-либо фильтр для захвата сообщения WM_ или если есть другие способы использования фильтров сообщений для достижения моей цели, также будет полезно.

  • в каких ДРУГИХ способах (кроме этого одного сообщения с сообщением message.msg = WM_WININICHANGE = 26, которое я нашел), могу ли я изменить свою заставку, отправить мне какое-то сообщение в мое приложение? возможно ли, что другой вид сообщения об изменении моей экранной заставки также фатален?

Сообщите мне, есть ли какая-либо другая информация о моей ситуации, которая может быть полезна, и я сделаю все возможное, чтобы получить ее! Заранее благодарю за любую помощь, которую вы можете дать:)

EDIT:

Появляется, если я ТОЛЬКО отправлю сообщение WM_CHANGESETTING и сделаю, чтобы моя программа ждала по длительности таймаута sendmessagetimeout, с которой я отправил сообщение, тогда моя программа не сбой... похоже, ОТВЕТ - это то, что разрушает мой программа... интересная. Я определенно близок к моему решению! Я думаю, что еще немного тестирования должно позволить мне выяснить метод, чтобы убедиться, что моя программа не отвечает на сообщение.

EDIT TWO:

Я обнаружил кое-что ОЧЕНЬ многообещающее сегодня: я определил свою функцию wndproc точно так:

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If CInt(m.Msg) <> CInt(26) Then
        MyBase.WndProc(m)
    Else
        MessageBox.Show("Get to work!", "Attention", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification)
    End If
End Sub

И затем я попытался запустить свою программу, а затем отправил сообщение WM_SETTINGCHANGE, используя:

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, IntPtr.Zero, _
             SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, IntPtr.Zero)

в другой программе, которую я сделал. Так что вы спросили? хорошо я пробовал это несколько раз, и каждый раз, когда всплывал ящик сообщений (слова, которые я выбрал для него, ничтожно), я пробовал ждать разного количества времени, прежде чем нажимать ok, а затем я увижу, что случилось с моей основной формой. Ну, много времени, ничего не изменилось, он все равно потерпел крушение. Но иногда, может быть, в 1/5 раза, программа по-прежнему будет реагировать после! Тогда, если бы это было так, я бы попробовал отправить сообщение снова, а затем снова, как правило, они будут терпеть неудачу во второй раз во время одного и того же запуска программы, НО иногда снова, примерно в 1/5 раза, казалось бы, программа не будет крушение СНОВА. И тогда я пытался дважды его разбить. и это не было ни разу, это почти всегда никогда не грохнуло бы независимо от того, сколько раз я пытался отправить сообщение и независимо от того, как долго я ждал после появления msgbox.

Я нашел, что ожидание около 5 секунд, казалось, увеличило мои шансы: моя форма, с которой я запускаю сообщение, все равно будет находиться в фокусе (верхняя панель будет синей), сразу после того, как я нажал кнопку замораживания, а затем появится msgbox вверх, а верхний также синий (в фокусе я предполагаю), оба они все еще "в фокусе" (по крайней мере синий ха-ха). Затем, примерно через 5 секунд, первоначальная форма потеряет фокус, и, увидев это, я попробую нажать "ОК".

В настоящее время я думаю, что это немного ожидание, а затем подтверждение поля сообщения иногда позволяет моей программе не вылетать, потому что она отключает сообщение, чтобы оно не возвращалось. Я НЕ знаю, почему сообщение, возвращающееся или нет, должно влиять на то, что делает моя программа. Это область, в которой разъяснение было бы полезно:)

ИЗМЕНИТЬ ТРИ:

поэтому я смотрю в Winspector немного больше, и я считаю, что, если я буду ждать появления WM_ERASEBKGND в моем рабочем окне (это окно, помеченное как "sysListView32" FolderView "в Winspector), прежде чем нажать" ОК ", на моем msgbox, тогда программа не будет разбиваться, интересно! Обычно для момента отправки сообщения WM_ERASEBKGND для момента появления сообщения sendmessagetimeout требуется близко к таймауту. это, конечно, после отправки сообщения WM_SETTINGCHANGE из моего домашнего тестового приложения.

Итак, после этого я решил немного посмотреть вокруг Winspector, потому что, может быть, есть еще более полезные очереди, которые я могу найти? Поскольку очевидно, что winspector, чтобы показать сообщение, отправлено на мой рабочий стол, не является фактическим исправлением для моей программы. В моем программном процессе я нахожу несколько необычно названных окон: один называется ".NET -BroadcastEventWindow.2.0.0.0.378734a.0", а другой называется "GDI + Hook Window Class" GDI + Window "с подстрокой под названием" IME ", Default IME".

Я решаю посмотреть сообщения, идущие в эти окна, чтобы узнать, получают ли они какие-либо узнаваемые сообщения, такие как WM_SETTINGCHANGE или WM_ERASEBKGND. Оказывается, они часто не получают сообщений: GDI + не получал никаких сообщений, пока я смотрел, я не думаю, но .NET -BroadcastEventWindow получил несколько. Те, которые идут в BroadcastEventWindow, были в основном только WM_appactivate, когда я щелкнул по окну своего приложения или в другом окне после него.

НО ТОГДА... Я замечаю .Net BroadcastEventWindow получает мое сообщение WM_CHANGESETTING!!!! Я смотрю на то, что появляются другие сообщения: не так много, но я замечаю, что при сбое приложения из-за ошибки появляется сообщение, которое я не распознаю: WM_USER + 7194 (0x201A). Хм, посмотрим, что это. После того, как я перейду в Google, я выясню, что это сообщение для приложения/пользователя, а затем после очередного поиска связанных с ним проблем я заметил, что кто-то может использовать фильтр для фильтрации этого сообщения и исправить проблему их (http://www.pcreview.co.uk/forums/handling-wm_user-messages-t1315625.html). Это стоит попробовать, по крайней мере, правильно? поэтому я снова добавляю фильтр, который я пытался ранее, и изменяю значения, которые нужно отфильтровать. Приложение не разбилось!!!!!!!

Далее я попробую, чтобы я заблокировал свою рабочую станцию, если это все еще выйдет из строя (потому что ранее было только с отправкой одиночного сообщения WM_CHANGESETTING). получается, что он все еще сработал:( НО, я еще раз посмотрю в winspector для этого окна, и о, два новых сообщения WM_USER: WM_USER + 7294 (0x207E) и WM_USER + 7189 (0x2015). Поэтому я пытаюсь их фильтровать тоже... и затем он не сбой при блокировке рабочей станции!!!: D

До сих пор я не заметил никаких негативных последствий этого при использовании обычного приложения! что имеет смысл, так как я не думаю, что какие-либо пользовательские сообщения целенаправленно участвуют в моей программе.

Я оставлю вопрос открытым дольше, пока не буду уверен, что в моем решении нет ничего плохого, и он работает хорошо. Спасибо тем, кто дал мне немного советов о том, как действовать на средних этапах моей отладки:)

4b9b3361

Ответ 1

Я видел эту проблему, упомянутую в разных вопросах на протяжении многих лет. Никогда не полностью диагностировал это, я просто скажу вам, что я знаю об этом.

Эта проблема связана с тем, как инициализируется класс SystemEvents. Он вовлечен в неудачу, потому что класс, который запускает событие, которое срабатывает при переключении на безопасный рабочий стол. Либо через экранную заставку, либо путем блокировки рабочей станции (клавиша Windows + L). Элементы управления Winforms в целом заинтересованы в событии SystemEvents.DisplaySettingsChanged, потому что им может потребоваться перерисовать себя при изменении темы или системных цветов. Это событие также часто возникает, когда система переключает рабочие столы.

Одна из основных проблем заключается в том, что события должны возникать в потоке пользовательского интерфейса. SystemEvents нужно точно угадать, какой поток фактически является потоком пользовательского интерфейса. Это происходит неправильно, когда первое окно, созданное в программе, создается в потоке, который на самом деле не является нитью пользовательского интерфейса, и в противном случае маскируется как один, если его квартира COM установлена ​​в STA. Если поток действительно продолжает работать, событие запускается в этом потоке. Если поток исчез, а не редко, тогда возникает исключение, когда SynchronizationContext.Post() пытается маршализовать вызов и терпит неудачу. Исключение проглатывается, и событие затем поднимается на произвольный поток threadpool.

В любом случае событие не создается в правильном потоке и что нарушает требования к потокам для любого компонента пользовательского интерфейса. Это имеет тенденцию оставаться незамеченным, по какой-то странной причине одно и то же событие, запущенное на рабочем столе, имеет тенденцию вызывать тупик или сбои намного чаще.

Вам нужно будет внимательно изучить код инициализации программы. Самой распространенной ошибкой является создание собственного заставки. Обязательно используйте встроенную поддержку в платформе .NET, чтобы получить это право.

Ответ 2

Внесите свой собственный фильтр сообщений с помощью

Public Class MyMessageFilter
    Implements IMessageFilter

    Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
        ' Return true for messages that you want to stop
        Return m.Msg = MessageToDiscard
    End Function
End Class

Добавьте этот фильтр, когда ваше приложение начнется с

Application.AddMessageFilter(New MyMessageFilter())