Как служба Windows может выполнить приложение с графическим интерфейсом? - PullRequest
43 голосов
/ 06 ноября 2008

Я написал службу Windows, которая позволяет мне удаленно запускать и останавливать приложения. Эти приложения запускаются с использованием CreateProcess, и это работает для меня, потому что большинство из них выполняют только внутреннюю обработку. В последнее время мне нужно запускать приложения, которые представляют графический интерфейс для текущего пользователя входа в систему. Как мне написать код на C ++, чтобы мой сервис мог найти активный в данный момент рабочий стол и запустить на нем графический интерфейс?

Ответы [ 9 ]

52 голосов
/ 06 ноября 2008

Ответ Роджера Липскомба, чтобы использовать WTSEnumerateSessions , чтобы найти правильный рабочий стол, затем CreateProcessAsUser , чтобы запустить приложение на этом рабочем столе (вы передаете ему дескриптор рабочего стола как часть структура STARTUPINFO ) правильная.

Однако я бы настоятельно рекомендовал не делать этого. В некоторых средах, таких как серверы терминалов со многими активными пользователями, определить, какой рабочий стол является «активным», нелегко и даже невозможно.

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

Более общепринятым подходом было бы создание ярлыка для небольшого клиентского приложения для вашей службы в глобальной группе запуска. Затем это приложение будет запускаться вместе с каждым сеансом пользователя и может использоваться для запуска других приложений (если это необходимо) без каких-либо манипуляций с учетными данными пользователя, сеансами и / или рабочими столами.

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

16 голосов
/ 06 ноября 2008

Короткий ответ: «Вы не делаете», поскольку открытие программы с графическим интерфейсом пользователя, работающей в другом пользовательском контексте, представляет собой уязвимость безопасности, широко известную как Shatter Attack .

Взгляните на эту статью MSDN: Интерактивные сервисы . Это дает возможность сервису взаимодействовать с пользователем.

Короче говоря, у вас есть следующие варианты:

  • Отображение диалогового окна в сеансе пользователя с использованием функции WTSSendMessage.

  • Создайте отдельное скрытое приложение с графическим интерфейсом и используйте функцию CreateProcessAsUser для запуска приложения в контексте интерактивного пользователя. Разработайте приложение с графическим интерфейсом для связи со службой через некоторый метод межпроцессного взаимодействия (IPC), например, именованные каналы. Служба связывается с приложением GUI, чтобы сообщить ему, когда отображать GUI. Приложение передает результаты взаимодействия пользователя обратно в службу, чтобы служба могла предпринять соответствующие действия. Обратите внимание, что IPC может предоставлять ваши сервисные интерфейсы по сети, если вы не используете соответствующий список контроля доступа (ACL).

    Если эта служба работает в многопользовательской системе, добавьте приложение в следующий ключ, чтобы оно запускалось в каждом сеансе: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run. Если приложение использует именованные каналы для IPC, сервер может различать несколько пользовательских процессов, назначая каждому каналу уникальное имя на основе идентификатора сеанса.

6 голосов
/ 06 ноября 2008

WTSEnumerateSessions и CreateProcessAsUser.

5 голосов
/ 06 ноября 2008

Несколько человек предложили WTSEnumerateSessions и CreateProcessAsUser. Интересно, почему никто не предложил WTSGetActiveConsoleSessionId, поскольку вы сказали, что хотите настроить таргетинг только на одного зарегистрированного пользователя.

Хотя некоторые люди действительно правы, предложите CreateProcessAsUser. Если вы называете простой старый CreateProcess так, как вы сказали, то графический интерфейс приложения будет работать с привилегиями вашего сервиса вместо привилегий пользователя.

2 голосов
/ 07 апреля 2010

Это проблемы Сессия 0, Интерактивные сервисы, Служба Windows Allow Service взаимодействует с рабочим столом в Windows 7 или Windows Vista

Вы можете прочитать эту статью http://www.codeproject.com/KB/vista-security/SubvertingVistaUAC.aspx

Я пытаюсь объяснить здесь, это работает на Windows 7

1 голос
/ 06 ноября 2008

На Win2K, XP и Win2K3 пользователь консоли входит в систему в сеансе 0, в том же сеансе, в котором живут службы. Если служба настроена как интерактивная, она сможет отображать пользовательский интерфейс на рабочем столе пользователя.

Однако в Vista ни один пользователь не может войти в систему в сеансе 0. Показ пользовательского интерфейса из службы немного хитрее. Вам нужно перечислить активные сеансы, используя WTSEnumerateSessions API, найти сеанс консоли и создать процесс от имени этого пользователя. Конечно, для этого вам также понадобятся токен или учетные данные пользователя. Подробнее об этом процессе можно прочитать здесь .

0 голосов
/ 19 февраля 2009

Важные службы не могут напрямую взаимодействовать с пользователем начиная с Windows Vista. Поэтому методы, упомянутые в разделе «Использование интерактивного сервиса», не должны использоваться в новом коде.

Это взято из: http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx

0 голосов
/ 06 ноября 2008

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

Но только если вы отрегулировали права доступа к сервису: вам нужно разрешить ему взаимодействовать с рабочим столом .

0 голосов
/ 06 ноября 2008

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

В любом случае, будьте очень осторожны, когда служба запускает exe.

Если доступ на запись в папку с exe-файлом не ограничен, любой пользователь может заменить этот exe-файл любой другой программой, которая затем будет запускаться с правами sytem. Взять, к примеру, cmd.exe (доступно для всех систем Windows). В следующий раз, когда служба попытается запустить ваш exe-файл, вы получите командную оболочку с системными правами ...

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