Як підвищити привілеї лише тоді, коли це потрібно?


85

Це питання стосується Windows Vista!

У мене є програма, яка зазвичай працює без адміністративних привілеїв. Існує одна діяльність, яка потребує адміністративних привілеїв, але я не хочу запускати саму програму з вищими привілеями, коли я знаю, що більшість випадків користувач навіть не використовує цю функцію.

Я думаю про певний метод, за допомогою якого я можу підвищити привілеї програми на якусь подію (наприклад, натискання кнопки). Приклад:

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

Відповіді:


58

Я не вірю, що можливо підняти поточний процес. Як я розумію, в Windows Vista вбудовано, що права адміністратора надаються процесу під час запуску. Якщо ви подивитесь на різні програми, які використовують UAC, ви повинні побачити, що вони насправді запускають окремий процес кожного разу, коли потрібно виконати адміністративну дію (диспетчер завдань - це одне, Paint.NET - інше, останнє фактично є додатком .NET ).

Типовим рішенням цієї проблеми є вказівка ​​аргументів командного рядка під час запуску підвищеного процесу (пропозиція Абатіщева є одним із способів зробити це), так що запущений процес знає лише відображення певного діалогового вікна, а потім завершує роботу після того, як ця дія була виконана завершено. Таким чином, користувачеві навряд чи повинно бути помітно, що новий процес був запущений, а потім вийшов з нього, і швидше за все виглядатиме так, ніби було відкрито нове діалогове вікно в тій самій програмі (особливо якщо вам потрібен хакер, щоб зробити головне вікно підвищений процес дитини дочірнього процесу). Якщо вам не потрібен інтерфейс для підвищеного доступу, ще краще.

Для повного обговорення UAC на Vista, я рекомендую вам переглянути цю наскрізну статтю на цю тему (приклади коду є на C ++, але я підозрюю, що вам потрібно буде використовувати WinAPI та P / Invoke, щоб зробити більшість речей на C # так чи інакше). Сподіваємось, ви зараз принаймні бачите правильний підхід, хоча розробляти програму, сумісну з UAC, далеко не тривіально ...


4
Чи є якісь зміни в Windows 7 чи відповідає відповідь "ні, використовуй новий процес"? Дякую ...
Радім Ванса

2
Жодних змін у Windows 7, боюся, вибачте. (Наскільки я знаю, і я звичайний користувач / розробник Win7.)
Noldorin

2
Саме так це робить диспетчер завдань. Коли ви натискаєте кнопку, щоб показати завдання для всіх користувачів, поточний диспетчер завдань викликає іншого диспетчера завдань з правами адміністратора.
Наталі Адамс

3
@NathanAdams Технічно він спочатку відкриває новий диспетчер завдань. Інакше, що робить відкриття? :-)
wizzwizz4

16

Як вже було сказано там :

Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";

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


Це передбачає охоплення нового процесу. так? Я шукав підвищення привілеїв самого поточного процесу.
Hemant

Спробуйте використати Process.GetCurrentProcess ()
абатищев

27
Ви не можете підняти поточний процес.
Jacob Proffitt

1
Це не правда. Ви можете змінити Власника процесу та встановити значення DACL та ACL для користувача, надаючи їм адміністративні повноваження ....
Nightforce2

4
@ nightforce2: безумовно, це спрацювало б, лише якщо у вас вже є адміністративні права (тобто ви вже підняті). В іншому випадку AdjustTokenPrivileges тощо просто не вдасться, ні?
Бен Швен

13

Наступна стаття КБ MSDN 981778 описує, як "самостійно підняти" програму:

http://support.microsoft.com/kb/981778

Він містить зразки для завантаження у Visual C ++, Visual C #, Visual Basic.NET.

Цей підхід обходить необхідність запускати окремий процес, але насправді це оригінальна програма, яка перезапускається, працюючи як підвищений користувач. Тим не менше, це все одно може бути дуже корисним у деяких контекстах, де не практично дублювати код в окремому виконуваному файлі.

Щоб зняти висоту, потрібно закрити програму.


1
Зручно для кнопки, але коли ви хочете те саме для пункту меню, вас чекає один справді заплутаний безлад.
Nyerguds

3
@Todd Ви можете знайти код тут: https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3
Matthiee,

Посилання відповіді мертве, а посилання коментаря вказує на довгий список 2608 елементів.
DonBoitnott

Ви можете знайти його тут
mirh


2

Можливо, комусь стане в нагоді цей простий приклад:

using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Security.Principal;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    internal static class Program
    {
        private class Form1 : Form
        {
            internal Form1()
            {
                var button = new Button{ Dock = DockStyle.Fill };
                button.Click += (sender, args) => RunAsAdmin();
                Controls.Add(button);

                ElevatedAction();
            }
        }

        [STAThread]
        internal static void Main(string[] arguments)
        {
            if (arguments?.Contains("/run_elevated_action") == true)
            {
                ElevatedAction();
                return;
            }

            Application.Run(new Form1());
        }

        private static void RunAsAdmin()
        {
            var path = Assembly.GetExecutingAssembly().Location;
            using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action")
            {
                Verb = "runas"
            }))
            {
                process?.WaitForExit();
            }
        }

        private static void ElevatedAction()
        {
            MessageBox.Show($@"IsElevated: {IsElevated()}");
        }

        private static bool IsElevated()
        {
            using (var identity = WindowsIdentity.GetCurrent())
            {
                var principal = new WindowsPrincipal(identity);

                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

    }
}

1

Я знаю, що це стара публікація, але це у відповідь на всіх, хто стикається з пропозицією MarcP. Повідомлення msdn, на яке він посилався, справді перезапускає програми у всіх прикладах коду. Зразки коду використовують runasдієслово, запропоноване вже в інших пропозиціях.

Я завантажив код, щоб переконатися, але це з оригінальної статті msdn:

4. Клацніть Так, щоб затвердити висоту. Потім оригінальна програма перезавантажується, працюючи під адміністратором.
5. Закрийте програму.


1
Чи можете ви додати відповідне посилання MSDN? Я не можу знайти користувача під назвою MarcP.
Альф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.