Повышение привилегий процесса программно?

147

Я пытаюсь установить службу с помощью InstallUtil.exe, но вызывается через Process.Start. Вот код:

ProcessStartInfo startInfo = new ProcessStartInfo (m_strInstallUtil, strExePath);
System.Diagnostics.Process.Start (startInfo);

где m_strInstallUtil- полный путь и исполняемый файл «InstallUtil.exe», а strExePathтакже полный путь / имя моей службы.

Запуск синтаксиса командной строки из командной строки с повышенными правами работает; Запуск из моего приложения (с использованием вышеуказанного кода) не. Я предполагаю, что имею дело с какой-то проблемой повышения прав, так как мне запустить мой процесс с повышенными правами? Нужно ли смотреть на ShellExecuteэто?

Это все в Windows Vista. Я запускаю процесс в отладчике VS2008 с повышенными правами администратора.

Я также попытался установить, startInfo.Verb = "runas";но это, похоже, не решило проблему.

Скотт Марлоу
источник
После того, как я добавил startInfo.UseShellExecute = true;в дополнение к startInfo.Verb = "runas";этому работал нормально для меня.
Мэтт

Ответы:

172

Вы можете указать, что новый процесс должен быть запущен с повышенными разрешениями, установив для свойства Verb вашего объекта startInfo значение runas, как показано ниже:

startInfo.Verb = "runas";

Это приведет к тому, что Windows будет вести себя так, как если бы процесс был запущен из Проводника с помощью команды меню «Запуск от имени администратора».

Это означает, что появится запрос UAC, и пользователь должен будет его подтвердить: если это нежелательно (например, потому что это может произойти в середине длительного процесса), вам необходимо запустить весь хост-процесс с повышенные разрешения для создания и встраивания манифеста приложения (UAC), требующие «наивысшего доступного» уровня выполнения: это приведет к тому, что приглашение UAC появится, как только ваше приложение будет запущено, и заставит все дочерние процессы запускаться с повышенными разрешениями без дополнительных запросов ,

Редактировать: Я вижу, вы только что отредактировали свой вопрос, чтобы заявить, что "runas" не работает для вас. Это действительно странно, как и должно быть (и делает для меня в нескольких производственных приложениях). Требование выполнения родительского процесса с повышенными правами путем встраивания манифеста, безусловно, должно работать.

MDB
источник
9
«Руны» у меня тоже не сработали. Может быть, он работает только с выключенным UAC?
Дирк Воллмар
18
@ LukePuplett Я бы поблагодарил их. Это отличный способ уменьшить установку руткитов без фактического разделения ролей пользователей.
Колтон
6
@ Sparksis, но есть и другая точка зрения. Люди, которые знают, как защитить свою ОС, знают, как это сделать без UAC. И фиктивные пользователи, которые не знают, что такое защита, они нажимают «ДА» каждый раз, когда видят окно UAC. Кроме того, ничто не может помешать злоумышленникам-вирусописателям использовать эксплойты, чтобы обойти это;) Поэтому я согласен с LukePuplett =)
Jet
24
Похоже, что вы также должны установить, startInfo.ShellExecute=trueчтобы это работало ... также я не смог заставить этот метод работать с исполняемыми файлами, находящимися в общем сетевом ресурсе (нужно скопировать их в локальный временный каталог перед запуском). ..
TCC
7
@Jet Извините, но это неправильное мышление. Каждый раз, когда диалоговое окно UAC отображается во время установки, это сбой системы. Там, где это ценно, вы видите блок UAC без запуска чего-либо, требующего повышения прав. Не имеет значения, насколько профессионально вы - любой из нас - думаете, что мы находимся на наших компьютерах, вы не можете волшебным образом заблокировать загрузку с нулевыми днями / без дисков (например, недавнюю на официальном сайте Нобелевской премии). Если бы вы зашли на этот сайт и получили приглашение UAC, вы бы знали, что что-то не так. С отключенным UAC вы никогда не узнаете, что присоединились к ботнету. Стоимость предварительного предупреждения заключается в том, что иногда приходится нажимать кнопку Да
Basic
46

Этот код объединяет все вышеперечисленное и перезапускает текущее приложение wpf с правами администратора:

if (IsAdministrator() == false)
{
    // Restart program and run as admin
    var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
    Application.Current.Shutdown();
    return;
}

private static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}


// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)

Обновление: способ манифеста приложения является предпочтительным:

Щелкните правой кнопкой мыши проект в Visual Studio, добавьте, новый файл манифеста приложения, измените файл так, чтобы вы установили requireAdministrator, как показано выше.

Проблема с оригинальным способом: если вы поместите код перезапуска в app.xaml.cs OnStartup, он все равно может ненадолго запустить главное окно, даже если было вызвано завершение работы. Мое главное окно лопнуло, если бы app.xaml.cs init не был запущен и в определенных условиях гонки это сделало бы это.

Кертис Яллоп
источник
Смотрите ниже для улучшения.
JCCyC
requireAdministrator не работает в моем случае. Поэтому я должен был сделать это по-своему. Это решило мою проблему! Спасибо. Но мне пришлось установить для Single Instance Application значение false.
Крис
Это сработало для меня. Я также передал оригинал string[] argsв новый процесс.
DotNetPadawan
21

В соответствии со статьей Крис Корио: научите свои приложения хорошо играть с управлением учетными записями пользователей Windows Vista, журнал MSDN, январь 2007 г. , только ShellExecuteпроверяет встроенный манифест и запрашивает повышение прав у пользователей, если это необходимо, CreateProcessа другие API этого не делают. Надеюсь, поможет.

Смотрите также: та же статья, что и .chm .

Восстановить Монику
источник
7
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

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

HB0
источник
3
Используя этот код, я получаю ошибку разрешения: «Запрос на разрешение объекта безопасности не выполнен». :(
Леонардо
Возможно, «если бегущий пользователь является членом Admin» *
hB0
1
интересно - это может быть любой метод, не только метод действия (я даже попробовал его на методе, определенном на странице ASPX)
Simon_Weaver
1

Вы должны использовать Олицетворение, чтобы поднять государство.

WindowsIdentity identity = new WindowsIdentity(accessToken);
WindowsImpersonationContext context = identity.Impersonate();

Не забудьте отменить олицетворенный контекст, когда закончите.

Виджеш В.П.
источник
28
Вы не сказали, как получить accessToken. LogonUser предоставит пользователю ограниченный контекст безопасности, когда UAC включен.
CWA
Если вы используете VSTS, вы можете получить Личный токен доступа из настроек на веб-портале. (Ищите значок настроек рядом с картинкой пользователя.) MSDocs
Су Ллевеллин