Я искал в Интернете ответ на этот вопрос, но, похоже, на него нет прямого ответа, поэтому я подумал, что спрошу.

Ситуационный сценарий: я хочу сделать снимок экрана того, что в данный момент отображается на экране компьютера. Если это экран входа в Windows, я хочу, чтобы он был именно таким. Если это рабочий стол активного пользователя, я хочу им быть. Если пользователь повышает уровень своего приложения и появляется приглашение UAC, я хочу, чтобы это было так.

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

  • Программа работает как служба Windows
  • Получает токен активного пользователя
  • Запускает CreateProcessAsUser с токеном пользователя для создания другого экземпляра самого себя
  • Делает снимок экрана и передает его обратно по каналам.

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

Кроме того, этот метод явно не работает для получения экрана входа в систему.

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

Спасибо всем!

1
user10530103 17 Ноя 2018 в 01:52

1 ответ

Лучший ответ

По совету Дэвисона я понял, как это сделать, и это включает в себя несколько шагов.

Во-первых, необходимо использовать CreateProcessAsUser для создания процесса внутри сеанса консоли (полученного из WTSGetActiveConsoleSessionId). Следует отметить, что этот процесс должен иметь административные привилегии, а простое получение дескриптора токена пользователя не годится. Очевидно, способ обойти это - получить дескриптор процесса, запущенного с административными привилегиями, получить токен этого процесса, продублировать его и использовать с CreateProcessAsUser. Я использовал для этого процесс Winlogon.

После этого все остальное довольно просто; используйте OpenInputDesktop, чтобы получить дескриптор рабочего стола, который пользователь в данный момент видит (он будет по умолчанию для реального рабочего стола, а Winlogon - для приглашения UAC и экрана входа в систему). После этого используйте SetThreadDesktop, чтобы установить поток ваших процессов на соответствующий рабочий стол и сделать снимок экрана. Предполагая, что у вашего процесса есть привилегии для создания дескриптора рабочего стола Winlogon, вы сможете захватывать экран входа в систему / приглашения uac и рабочий стол обычного пользователя.

Опять же, спасибо Дэвисону, который указал мне правильное направление.

0
user10530103 17 Ноя 2018 в 18:14