Обнаружение подключения к удаленному рабочему столу из службы при входе в систему (W7/32)

Я знаю (и это работает), что в C# это свойство сообщает мне, является ли текущий сеанс сеансом RDP:

System.Windows.Forms.SystemInformation.TerminalServerSession

Теперь у меня есть служба, которая получает события входа в систему/выхода из системы и блокировки/разблокировки, и мне нужен способ сообщить этой службе, является ли запущенный сеанс rdp или локальным.

Проблема: служба работает от имени пользователя SYSTEM, а указанное выше свойство всегда возвращает false (я думаю, потому что SYSTEM всегда считается локальным подключенным пользователем)

Я попытался найти в реестре подраздел Volatile Environment, чтобы проверить, существует ли подраздел, идентифицирующий имя сеанса RDP: это работает в обработчике блокировки/разблокировки, но в обработчике входа подраздел еще не существует (подключ создается после завершения входа в систему).

Любая идея о том, как обойти эту проблему?

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


person Axeman    schedule 24.07.2012    source источник
comment
Это не потому, что служба запускается из SYSTEM, а просто потому, что это служба. Все службы работают в сеансе 0, который по определению является локальным. Какую информацию о новом входе вы сейчас получаете? Доступные функции API см. здесь: msdn.microsoft.com/en-us/library/windows/desktop/   -  person Harry Johnston    schedule 25.07.2012
comment
Информация, которая у меня есть при новом входе в систему, это та, которую я могу прочитать из нестабильной среды, и ничего больше. И каждый запрос, который я могу выполнить в подсистеме WTS для текущего сеанса, как вы сказали, говорит, что соединение является локальным, поэтому я не могу получить от них информацию. Думаю, я попытаюсь найти способ перечислить все сеансы WTS и извлечь информацию из каждого из них. На наших машинах существует принудительное ограничение только на один одновременный сеанс RDP, поэтому я ожидаю найти не более одного сеанса с данными rdp. QuerySessionInfos в этом сеансе должен дать мне нужные мне данные... (надеюсь)   -  person Axeman    schedule 25.07.2012
comment
Если вы получаете уведомление о входе в систему через событие SERVICE_CONTROL_SESSIONCHANGE, структура WTSSESSION_NOTIFICATION включает идентификатор сеанса. Вам нужно только запросить этот конкретный сеанс.   -  person Harry Johnston    schedule 25.07.2012
comment
@HarryJohnston Отлично! Завтра я изменю код, чтобы сделать то, что вы предложили. Спасибо.   -  person Axeman    schedule 26.07.2012


Ответы (1)


Вы можете определить, является ли сеанс локальным или удаленным, позвонив WTSQuerySessionInformation с параметром WTSInfoClass, установленным на WTSClientProtocolType. Если вы предпочитаете избегать P/Invokes, вы можете использовать библиотеку Cassia: new TerminalServicesManager().GetLocalServer().GetSession(sessionId).ClientProtocolType .

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

person Dan Ports    schedule 25.07.2012
comment
Я не знал об этой библиотеке... очень-очень интересно, спасибо!. Насчет выхода из системы проблем нет, потому что сервису нужно проверять тип протокола только при входе в систему. - person Axeman; 26.07.2012