Найти MessageBox в конкретном приложении?

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

Проблема была в том, что если пользователь находится далеко от своего рабочего стола, у него может быть более 20 окон сообщений при возвращении. Так что мы пытаемся выяснить, отклонили ли они окно сообщения или нет. Если они не уволены, нет причин показывать другую.

Они могут не только иметь несколько запущенных наших различных приложений, которые реализуют эту функциональность, но также они могут иметь несколько запущенных приложений, просто подключенных к другой среде.

Мне удалось найти окна сообщений с помощью FindWindow, но я не знал, какому конкретному экземпляру какого приложения оно принадлежит, поэтому я не могу просто предположить, что оно принадлежит текущему экземпляру. Я надеялся на работу FindWindowEx, просто передав дескриптор владельца окна сообщения в вызов API, но у меня ничего не получилось. Всегда возвращает ноль.

Код, который я покажу, находится на vb.net, но я хорошо разбираюсь в C# и vb.net, поэтому не имеет значения, в какой форме приходит решение.

В любом случае здесь есть код, который выдает уведомление:

Private Sub InitDeploymentCheck()
    moDeploymentCheck = New TRS.Deployment.TRSDeploymentCheck(EnvironmentVariables.Environment, AppDomain.CurrentDomain.BaseDirectory.Contains("bin"), MDIMain)
    AddHandler moDeploymentCheck.DeploymentNeeded,
        Sub()
            moTimer = New Timer()
            moTimer.Interval = 300000 '5 minutes
            moTimer.Enabled = True
            AddHandler moTimer.Tick,
                Sub()
                    'check to see if the message box exist or not before throwing up a new one
                    MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
                End Sub
            MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End Sub

Я смог найти окно:

Dim handle As IntPtr = FindWindow(Nothing, "Critical Deployment")

Вот как я пытался найти окно с FindWindowEX:

Dim t As IntPtr = FindWindowEx(200398, IntPtr.Zero, "Form", "Critical Deployment")

200398 - это ручка от mdimain выше.

2 ответа

Решение

Когда у вас есть HWND ручку к окну, вы можете использовать GetWindowLong(GWL_HINSTANCE) или же GetWindowThreadProcessId() проверить, к какому экземпляру приложения относится окно. использование EnumWindows() перечислить все окна верхнего уровня, где ваша функция обратного вызова проверяет заголовок и экземпляр процесса каждого сообщаемого окна, пока не найдет искомое совпадение.

Почему бы просто не использовать именованный EventWaitHandle, который указывает, отображается ли одно из этих окон сообщений в данный момент? Все ваши приложения могут подписаться на это событие. Когда приложение видит, что пришло время отобразить окно сообщения, оно проверяет, установлен ли дескриптор ожидания. Если он не установлен, приложение устанавливает событие и отображает окно сообщения. Когда окно сообщения закрывается, приложение сбрасывает событие. Если событие установлено при проверке, приложение просто не отображает сообщение.

Это намного проще, чем FindWindow а также EnumWindows,

Другие вопросы по тегам