Как повысить привилегии только при необходимости?


этот вопрос относится к Windows Vista!

У меня есть приложение, которое нормально работает без административных привилегий. Существует одно действие, которое требует административных привилегий, но я не хочу запускать само приложение с более высокими привилегиями, когда я знаю, что большую часть времени пользователь даже не будет использовать эту функцию.

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

если пользователь нажимает эту кнопку, то ему предлагается диалоговое окно UAC или согласие. Как я могу это сделать?

6 80

6 ответов:

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

типовое решение к этой проблеме относится указание аргументов командной строки при запуске повышенного процесса (предложение абатищева-один из способов сделать это), чтобы запущенный процесс знал только отображение определенного диалогового окна, а затем выход после завершения этого действия. Таким образом, для пользователя вряд ли должно быть заметно, что новый процесс был запущен, а затем вышел, и скорее будет выглядеть так, как будто новое диалоговое окно в том же приложении было открыто (особенно если вы какой-то хакер, чтобы сделать основной окно повышенного процесса дочерний родительский процесс). Если вам не нужен пользовательский интерфейс для повышенного доступа, еще лучше.

для полного обсуждения UAC на Vista, я рекомендую вам посмотреть это очень Через статьи по этому вопросу (примеры кода находятся в C++, но я подозреваю, что вам нужно будет использовать WinAPI и P/Invoke, чтобы сделать большинство вещей в C# в любом случае). Надеюсь, теперь вы, по крайней мере, видите правильный подход, хотя разработка совместимой с UAC программы далека тривиальный...

Как сообщил здесь:

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

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

в следующей статье 981778 MSDN KB описывается ,как "самостоятельно поднять" приложение:

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

содержит примеры в Visual C++ или Visual C# в Visual Basic.NET.

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

чтобы удалить высоту, вам нужно выйти из приложения.

вам нужен моникер UAC и код для запуска с повышенными правами в качестве COM-объекта.

посмотреть этот вопрос.

документация по MSDN.

Я знаю, что это старый пост, но это в ответ на все, кто сталкивается с предложением MarcP. Сообщение msdn, на которое он ссылался, действительно перезапускает приложения во всех примерах кода. В примерах кода используется runas глагол предложен уже в других предложениях.

Я загрузил код, чтобы убедиться, но это из оригинальной статьи msdn:

4. Нажмите кнопку Да, чтобы утвердить высоту. Затем, оригинальное приложение перезапуски, Запуск от имени администратора с повышенными правами.
5. Закрыть приложение.

возможно кому-то пригодится этот простой пример:

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);
            }
        }

    }
}