Предотвратить процесс 'A' от порождения процесса 'B', который затем отображается поверх того, что должно быть “самым верхним” Процессом 'C'

StackOverflow https://stackoverflow.com/questions/1132831

Вопрос

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

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

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

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

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

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


Добавление:

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

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ 2:Если хорошенько подумать...может быть, explorer.exe не нужен.Я попробую и отчитаюсь.

Редактировать 3:Не удалось заставить код, приведенный в этой статье, работать.Придется на минутку отложить это.


Краткое содержание ответа

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

Это было полезно?

Решение

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

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

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

Добавление:

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

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

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

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

Другие советы

Вы можете использовать Класс процесса для начала flash.exe непосредственно - и используйте соответствующий Информация о запуске процесса настройки для отображения окна в скрытом состоянии - или со стилем окна скрытый или свернутый.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top