Не позволяйте процессу «А» порождать процесс «Б», который затем появляется поверх того, что должно быть самым верхним процессом «С»

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

Существует стороннее приложение (называемое player.exe), которое отображает файлы фильмов SWF на той части экрана, которая всплывает поверх моего приложения.

С помощью Process Monitor я определил, что приложение player.exe вызывает
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
в моем случае:
flash.exe 901 96 379 261 somemovie.swf

Поскольку flash.exe создается в новом процессе после того, как моя форма была установлена ​​​​на TopMost, он появляется поверх моего приложения.

Первое, что я сделал, это заставил мое приложение минимизировать главное окно приложения player.exe, надеясь, что это предотвратит появление Flash. Но, к сожалению, это не так... даже когда окно свернуто, всякий раз, когда запускается флэш-ролик, оно отображается в месте расположения пикселя (901,96). Затем я попытался создать таймер, чтобы устанавливать для свойства form.TopMost значение true каждые 10 мс. Это работает, но вы все еще видите очень быстрое изображение swf-файла.

Есть ли какой-либо тип вызова Windows API, который можно использовать для временного запрета player.exe создавать видимые дочерние процессы? Признаюсь, это звучит немного надуманно. Но любопытно, сталкивался ли кто-нибудь с подобной проблемой.


Приложение:

Это дополнение должно дать ответ на некоторые предложения, изложенные в сообщении Мэтью ниже.

Для чрезвычайной ситуации, описанной в комментариях, я бы рассмотрел возможные решения в следующих направлениях:

1) Как обычно запускается и останавливается стороннее приложение? Могу ли я закрыть его таким же образом? Если это служба, диспетчер управления службами может ее остановить. Если это обычное приложение, отправка управляющего нажатия клавиши (возможно, с помощью SendInput()) или сообщения WM_CLOSE в его главное окно может работать.

Самый простой способ закрыть приложение — нажать CTRL-ALT-DEL, а затем завершить процесс. -ИЛИ- Правильный способ - удерживать ESC, нажимая левую кнопку мыши... затем введите свое имя пользователя и пароль, перейдите в некоторые меню, чтобы остановить проигрыватель.

Команды PAUSE нет... хотите верьте, хотите нет.

Я не думаю, что использование WM_CLOSE поможет, так как сворачивание приложения не поможет. Это также убьет процесс? Если нет, то как открыть заново.

2) Если я не могу закрыть его красиво, могу ли я его убить? Если это так, TerminateProcess() должен работать.

Я не могу убить процесс по двум причинам. 1) При перезапуске вам необходимо указать учетные данные имени пользователя/пароля... Может быть способ обойти это, так как он не запрашивает, когда машина перезагружается, но... 2) Всякий раз, когда я убиваю процесс в диспетчере задач < strong>он не умирает изящно и спрашивает, хотите ли вы отправить отчет об ошибке.

3) Если мне абсолютно необходимо оставить другой процесс запущенным, я попытаюсь посмотреть, смогу ли я программно вызвать быстрое переключение пользователей, чтобы перейти к другому сеансу (в котором не будет конкурирующих окон). Я не знаю, с чего в API начать с этого. (Питер Рудерман предлагает SwitchDesktop() для этой цели в своем ответе.)

Меня очень вдохновила эта идея... Я нашел эту статью на сайте CodeProject. который предоставляет множество методов API-оболочки. Я прекратил его реализацию, потому что я думаю, что для того, чтобы рабочий стол работал, у вас должен быть запущен explorer.exe (чего у меня нет).

EDIT2: Если подумать... может быть, explorer.exe не нужен. Я попробую и отчитаюсь.

Edit3: не удалось заставить работать код в этой статье. Придется отложить это на мгновение.


Резюме ответа

Как и следовало ожидать, простого ответа на эту проблему не существует. Лучшим решением было бы проблематично переключиться на другой рабочий стол, когда вам нужно гарантировать, что на нем ничего не появится. Мне не удалось найти простую реализацию переключения рабочих столов на C#, которая работала, и у меня возникло подозрение, что я просто открою совершенно новый набор червей, как только она будет реализована. Поэтому я решил не реализовывать переключение рабочих столов. Я нашел реализация C++, которая хорошо работает. Опубликуйте работающий виртуальный рабочий стол C#. реализации для других.


person blak3r    schedule 15.07.2009    source источник
comment
На днях я немного поболтал с окном. Это дно. Он сказал, что ненавидит, как другие окна полностью заглушают его, становясь вершиной. Ему так надоело быть нижним всю свою жизнь, что он решил, что пора тоже стать верхом. А теперь все окна топы. И все они конкурируют друг с другом. Но у них нет пары, потому что они все лучшие.   -  person uSeRnAmEhAhAhAhAhA    schedule 10.11.2013
comment
Вы видите, к чему я клоню? Это бесконечный порочный круг, который мы должны разорвать. У нас всегда будет эта проблема, потому что каждое окно хочет быть TopMost.   -  person uSeRnAmEhAhAhAhAhA    schedule 10.11.2013


Ответы (3)


Установка свойства TopMost (или добавление стиля WS_EX_TOPMOST к окну) не делает его уникальным в системе. Любое количество самых верхних окон может быть создано любым количеством приложений; единственная гарантия заключается в том, что все самые верхние окна будут нарисованы «над» всеми не самыми верхними окнами. Если есть два или более верхних окна, Z-порядок все еще применяется. Из вашего описания я подозреваю, что flash.exe также создает самое верхнее окно.

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

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

Дополнение:

Для чрезвычайной ситуации, описанной в комментариях, я бы рассмотрел возможные решения в следующих направлениях:

  1. Как обычно запускается и останавливается стороннее приложение? Могу ли я закрыть его таким же образом? Если это служба, диспетчер управления службами может остановить. Если это обычное приложение, отправка управляющей клавиши (с SendInput() возможно) или WM_CLOSE в его главное окно может работать.

  2. Если я не могу закрыть его красиво, мне разрешено его убить? Если это так, TerminateProcess() должен работать.

  3. Если мне абсолютно необходимо оставить другой процесс запущенным, я попытаюсь посмотреть, смогу ли я программно вызвать быстрое переключение пользователей, чтобы перейти к другому сеансу (в котором не будет конкурирующих окон верхнего уровня). Я не знаю, с чего в API начать с этого. (Питер Рудерман предлагает SwitchDesktop() для этого цель в его ответе.)

person Matthew Xavier    schedule 15.07.2009
comment
@Matthew Xavier Обычно я согласен с вашим предложением не вмешиваться в компьютеры пользователей. В данном случае заявка предназначена для системы экстренного оповещения. Компьютер — это не персональный компьютер, а специальная система управления контентом, которая генерирует видеоизображение для ЖК-экранов или плазменных экранов, расположенных по всей организации. Заказчику нужен способ переопределить содержимое во время чрезвычайной ситуации. Какие-либо предложения? Хороший пост! - person blak3r; 15.07.2009
comment
@Matthew Xavier Спасибо за все ваши предложения. Я ответил на ваше дополнение в вопросе. - person blak3r; 17.07.2009

Вы можете использовать класс Process для запуска флэш-памяти. exe напрямую и используйте соответствующие настройки ProcessStartInfo для показать окно в скрытом состоянии - или со скрытым или свернутым WindowStyle.

Вы также можете использовать API SetWindowsHookEx для перехватите вызовы API запуска процесса, и когда процесс flash.exe запустите некоторый код, чтобы восстановить ваше окно до самого верхнего состояния.

person LBushkin    schedule 15.07.2009
comment
Это стороннее приложение, которое запускает flash. Таким образом, я не имею над ним контроля. Я думаю, что приложение было разработано плохо. - person blak3r; 15.07.2009

Ответ Мэтью превосходен, но я подозреваю, что вы задаете неправильный вопрос. Почему ваше приложение должно быть самым верхним? Если вы пытаетесь создать киоск или что-то в этом роде, то самое верхнее — не лучший вариант.

Редактировать. Прочитав ваш ответ на комментарий Мэтью, я предлагаю создать новый рабочий стол и переключиться на него, прежде чем отображать предупреждение. (См. раздел CreateDesktop и SwitchDesktop в MSDN.)

person Peter Ruderman    schedule 15.07.2009