Запуск другого процесса с повышением с использованием разных учетных данных пользователя
Я пытаюсь запустить процесс с невыполненным процессом, но мне также нужно указать имя пользователя и пароль для пользователя с учетными данными администратора. Я пробовал использовать метод "runas"
для повышения, а также использовать манифест, но оба дают разные ошибки.
Например, если я делаю это (без использования манифеста, требующего повышения):
ProcessStartInfo info = new ProcessStartInfo(path);
info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";
var proc = Process.Start(info);
Процесс запускается без отображения диалогового окна подтверждения UAC и не удается выполнить команду, требующую прав администратора (я просто пытаюсь записать тестовый файл в каталог Program Files).
Если я добавлю манифест в целевое приложение, которое указывает, что для него требуется возвышение, я получаю Win32Exception
, заявляя, что операция требует повышения.
Кажется, что проблема заключается в настройке UseShellExecute
на false
(поскольку оба подхода работают нормально, когда это не так), но я должен установить для него значение false, чтобы запустить процесс под другой учетной записью пользователя.
Как я могу запустить повышенный процесс из процесса без повышения и вручную указать имя пользователя и пароль?
BOUNTY EDIT: В то время как пользователю не требуется вводить учетные данные администратора, вполне возможно, что диалог UAC nag вполне допустим. Я не собираюсь обойти UAC здесь.
Ответы
Ответ 1
я был удивлен, что нет никакого способа сделать это, пока я не нашел запись в блоге Криса Джексона:
Вам нужен начальный загрузчик. Некоторый процесс, который позволит вам выполнить переход к альтернативному пользователю, который может быть ответственным за запуск приложения requireAdministrator. Итак, вы можете создать что-то вроде этого:
![enter image description here]()
Почему бы нам просто не создать API ShellExecuteWithLogonW
? Я никогда не скажу никогда, и мы могли бы в какой-то момент. Но сегодня, варианты использования для этих API были вариантами использования, когда был альтернативный дизайн, который является превосходящим.
Наиболее распространенный запрос - для людей, пишущих собственное программное обеспечение для развертывания программного обеспечения, где они хотят кодировать учетные данные прямо в приложение и повышать свой собственный процесс. Реальная проблема здесь не в отсутствии API, а в том, что у вас есть учетные данные администратора, закодированные в вашем приложении, чтобы читатели могли их прочитать.
Таким образом, для решения требуется ShellExecute
, единственное, кто знает, как вызвать диалог Согласие.
Это поднимает хороший вопрос: что вы уже делаете с паролем человека?
Бонусная болтовня
Там нет UAC на Server Core, потому что нет окон для отображения запроса на согласие.
Ответ 2
Из MSDN:
Вы не можете поднять уже запущенный процесс. Таким образом, вы должны реорганизовать ваше приложение для разделения на административные и неадминистративные операции - запуск приложения по умолчанию с обычными привилегиями и запуск другой повышенный процесс для каждой административной операции.
Позвольте работать с этим, если вы запрашиваете права администратора с самого начала на требуемые процессы. На основе контекста, который вы предоставили:
Кажется, что проблема заключается в установке UseShellExecute
в false
(поскольку оба подходы работают нормально, когда это не так), но я должен установить его на false, чтобы запустить процесс под другим пользователем счет.
Как вы упомянули, точно так же, как указано в документации для UseShellExecute
:
UseShellExecute должен быть false, если свойство UserName не является Nothing или пустая строка, или исключение InvalidOperationException когда вызывается метод Process.Start(ProcessStartInfo).
Теперь мы знаем, что вы выполняете свою программу напрямую, а не с помощью оболочки. Это ценная информация.
Просматривая документацию, документы для ProcessStartInfo
содержат следующее примечание по безопасности:
Этот класс содержит потребность в ссылке на уровне класса, которая применяется к все участники. Исключение SecurityException бросается, когда непосредственный вызывающий не имеет полного доверия. Подробнее о безопасности требования, см. Запрос связи.
Итак, у вас нет правильного запроса на связь. При попытке решить проблему с разрешениями вы случайно создали другую проблему с разрешениями.
Вы должны украсить свой метод вызова с помощью Требование безопасности, которое должно быть FullTrust
. Вы можете сделать это декларативно или императивно в вашем коде.
(Дополнительное чтение)
Ответ 3
Если вы создаете приложение для Windows Installer (MSI) и обновляете его с помощью MSP, то установщик Windows имеет встроенную поддержку именно для вашего сценария: - проверьте Контроль учетных записей пользователей (UAC).
Он работает в основном так:
- Когда вы создаете оригинальный MSI, вы создаете сертификат, и вы помещаете его открытый ключ (или что-то в этом роде) в MSI.
- Администратор конечной машины устанавливает MSI на машине.
- Вы публикуете обновление (MSP) и подписываете его с сертификатом.
- Любой пользователь на целевом компьютере теперь может установить обновление. Установщик Windows проверит сертификат на открытый ключ в исходном MSI и соглашается установить, если это так. Я не думаю, что вы получите приглашение UAC вообще, хотя я не уверен.
Ответ 4
В соответствии с документацией MSDN:
Когда UseShellExecute является ложным, вы можете запускать только исполняемые файлы, используя объект "Процесс".
Я заметил, что ваша декларация var proc = Process.Start(info);
не использует Process
как тип класса.
Также убедитесь, что параметр path
- это полный путь к исполняемому файлу. Например, "c:\\directory\\contains\\process_to_be_started\\executable.exe"
В соответствии с документацией MSDN это важно:
Свойство WorkDirectory должно быть установлено, если UserName и Password предоставлена. Если свойство не установлено, рабочим каталогом по умолчанию является % SYSTEMROOT%\system32.
Я бы попробовал ниже код для запуска целевого процесса с повышенными привилегиями (с правами администратора).
ProcessStartInfo info = new ProcessStartInfo(path);
info.UseShellExecute = false;
info.UserName = username;
info.Password = securePwd;
info.Domain = "MyDomain";
info.Verb = "runas";
info.WorkingDirectory = "c:\\directory\\contains\\process_to_be_started"
'var proc = Process.Start(info);
Process proc = Process.Start(info);
Ответ 5
ProcessStartInfo.Verb="runas"
предназначен только для Windows Vista и выше, поэтому вы должны запросить системный уровень, а не делать возвышение для XP.
Я думаю, что если вы выберете ProcessStartInfo.Verb="runas"
, вы не должны указывать имя пользователя и пароль.
Если UAC имеет значение, значит, он все равно преуспел, это не должно быть проблемой.