Если это вообще возможно, используйте вместо этого решение Ларри Остермана (в комментариях к ответу Андерса), т. Е. Используйте родительский процесс, который выполняется без повышения прав, и запускайте как процесс с повышенными правами, так и процесс без повышенных прав.
Если это невозможно, есть подход, который должен работать почти во всех случаях, хотя обычно это больше проблем, чем стоит:
Установите и запустите системную службу, настроенную для работы в качестве локальной системы. Присвойте ему идентификатор сеанса удаленного рабочего стола, например, через аргумент командной строки или параметр реестра, а также идентификатор процесса и командную строку, которую вы хотите запустить.
Из системной службы используйте GetTokenInformation с TokenLinkedToken, чтобы получить связанный токен из целевого процесса. Вы должны сделать это из системной службы, потому что вам нужен SE_TCB_NAME, чтобы получить токен, который можно использовать. (Это ограничение, похоже, не задокументировано, но соответствует поведению токенов в Windows.)
Или, если нет связанного токена, используйте WTSQueryUserToken , чтобы получить копию токена пользователя. Я считаю, что это всегда дает вам ограниченный токен (если он есть), но если вы хотите быть в безопасности, вы можете проверить, является ли он токеном с повышенным или ограниченным доступом, используя GetTokenInformation и TokenElevationType; если это токен с повышенными правами, вы можете использовать TokenLinkedToken, чтобы получить ограниченный токен.
Если нет связанного токена (TokenElevationTypeDefault), вы должны использовать токен как есть. Это может произойти либо потому, что пользователь не является администратором, либо потому что UAC отключен, либо глобально, либо потому, что пользователь вошел в систему с использованием встроенной учетной записи администратора. Если пользователь не является администратором, токен уже подходит. Если UAC отключен, вы должны уважать намерения пользователя и использовать административный токен.
Затем вы можете использовать CreateProcessAsUser или CreateProcessWithTokenW из системной службы для запуска нового процесса.
Наконец, служба должна удалить себя и остановить.
Существует как минимум один крайний случай: если ваш повышенный процесс запускается из командного окна (или другого процесса), которое было запущено с использованием runas и неадминистративных учетных данных. В этом случае нет разделенного токена, и исходный токен, возможно, уже был удален, поэтому, если вы не захватили копию до того, как произошло повышение прав (решение Ларри или его варианты), не существует общего способа запустить дочерний процесс в том же самом пользовательский контекст, из которого изначально был запущен повышенный процесс. Лучшее, что вы можете сделать, - это контекст вошедшего в систему пользователя (через WTSQueryUserToken, как описано выше), который может не соответствовать поведению, ожидаемому конечным пользователем. (Однако это может быть приемлемым ограничением в зависимости от сценария.)