Підвищення привілеїв процесу програмно?


147

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

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

де m_strInstallUtilє повністю кваліфікований шлях та exe до "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" для вас не працює. Це дійсно дивно, як і слід (і для мене це є в декількох виробничих додатках). Однак вимагати, щоб батьківський процес запускався з підвищеними правами шляхом вбудовування маніфесту, безумовно, повинен працювати.


9
"runas" також не працював для мене. Може бути, він працює лише з вимкненим UAC?
— Дірк Волмар

18
@LukePuplett Я б вдячний їм. Це прекрасний спосіб пом'якшити встановлення root-kit, не фактично повністю розділивши ролі користувача.
— Колтон

6
@Sparksis, але є й інша точка зору. Люди, які вміють захищати свою ОС, знають, як це зробити без UAC. І фіктивні користувачі, які не знають, що таке захист, вони щоразу, коли бачать вікно UAC, клацають "ТАК". Також ніщо не може перешкодити злочинцям-авторам-вірусам використовувати подвиги, щоб обійти його;) Тож я згоден з LukePuplett =)
— Jet

24
Схоже, ви повинні налаштувати startInfo.ShellExecute=trueтак, щоб це працювало ... також мені не вдалося змусити цей метод працювати з виконуваними файлами, які знаходяться в мережевій спільній доступності (перед запуском доводиться копіювати їх у локальну тимчасову директорію). ..
— TCC

7
@Jet Вибачте, але це неправильне мислення. Кожен раз, коли під час встановлення відображається діалогове вікно UAC, це є збоєм у роботі системи. Де це цінно, коли ви бачите поле UAC, не запускаючи щось, що вимагає піднесення. Не важливо, наскільки ви, будь-хто з нас, думаєте, що ми працюємо на своїх ПК, ви не можете магічно заблокувати завантаження нульових днів / драйверів (наприклад, останні на офіційному сайті Нобелівської премії). Якщо ви перейшли на цей сайт і отримали підказку UAC, ви б знали, що щось не так. З вимкненим UAC ви ніколи не дізнаєтесь, що тільки що приєдналися до ботнету. Вартість попереднього попередження полягає в тому, що потрібно періодично клацати Так
— Основні

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)

Оновлення: спосіб маніфесту додатка бажаний:

Клацніть правою кнопкою миші проект у візуальній студії, додайте, новий файл маніфесту програми, змініть файл, щоб у вас був набірAdAd Administrator, як показано вище.

Проблема з оригінальним способом: Якщо ви помістите код перезавантаження в app.xaml.cs OnStartup, воно все ще може ненадовго запустити головне вікно, навіть незважаючи на закриття. Моє головне вікно вибухнуло, якщо app.xaml.cs init не був запущений і в певних умовах гонки це зробить.


Детальнішу інформацію див. Нижче.
— JCCyC

requAdministrator не працював у моєму випадку. Тому я повинен був зробити це по-своєму. Це вирішило мою проблему! спасибі. Але мені довелося встановити програму Single Instance на значення false.
— chris

Це працювало для мене. Я також передав оригінал string[] argsдо процесу відновлення.
— DotNetPadawan

21

Згідно зі статтею Кріс Коріо: Навчіть свої програми прекрасно грати за допомогою контролю облікових записів користувачів Windows Vista, журнал MSDN, січень 2007 року , лише ShellExecuteперевіряє вбудований маніфест і при необхідності підказує користувача на підвищення, в той час як CreateProcessінші API не роблять цього. Сподіваюся, це допомагає.

Дивіться також: та сама стаття, як .chm .


7
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

Це обійдеться без UAC - не потрібно починати новий процес. Якщо поточний користувач є членом групи адміністраторів, як у моєму випадку.


3
Використовуючи цей код, я отримую помилку дозволу: "Запит дозволу суб'єкта безпеки не вдався." :(
— Леонардо

Можливо, "Якщо поточний користувач є членом адміністратора" *
— hB0

1
що цікаво - це може бути застосовано будь-який метод, а не лише метод дій (я навіть спробував це на методі, визначеному на сторінці ASPX)
— Simon_Weaver

1

Ви повинні використовувати себе, щоб підняти державу.

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

Не забудьте скасувати підроблений контекст, коли закінчите.


28
Ви не сказали, як отримати accessToken. LogonUser надасть користувачеві обмежений контекст безпеки при включенні UAC.
— cwa

Якщо ви використовуєте VSTS, ви можете отримати маркер особистого доступу з налаштувань веб-порталу. (Шукайте значок налаштування поруч із зображенням користувача.) MSDocs
— Su Llewellyn
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.