C# 如何仅在需要时提升权限?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/573086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:47:35  来源:igfitidea点击:

How to elevate privileges only when required?

c#.netwindows-vistauacprivileges

提问by Hemant

This question applies to Windows Vista!

此问题适用于 Windows Vista!

I have an application which normally works without administrative privileges. There is one activity which does need administrative privilege but I don't want to start the application itself with higher privileges when I know most of time user wont even be using that feature.

我有一个通常无需管理权限即可运行的应用程序。有一项活动确实需要管理权限,但是当我知道大多数时候用户甚至不会使用该功能时,我不想以更高的权限启动应用程序本身。

I am thinking about certain method by which I can elevate the privileges of application on some event (such as press of a button). Example:

我正在考虑某种方法,通过该方法我可以在某些事件(例如按下按钮)上提升应用程序的权限。例子:

If user clicks this button then he is prompted with UAC dialog or consent. How can I do this?

如果用户单击此按钮,则会提示他提供 UAC 对话框或同意。我怎样才能做到这一点?

采纳答案by Noldorin

I don't believe that it is possible to elevate the currently running process. It is built into Windows Vista that administrator privileges are given to a process upon startup, as I understand. If you look at various programs that utilise UAC, you should see that they actually launch a separate process each time an administrative action needs to be performed (Task Manager is one, Paint.NET is another, the latter being a .NET application in fact).

我不相信可以提升当前正在运行的进程。据我了解,Windows Vista 内置了在启动时向进程授予管理员权限的功能。如果您查看使用 UAC 的各种程序,您应该看到它们实际上在每次需要执行管理操作时启动一个单独的进程(任务管理器是一个,Paint.NET 是另一个,后者实际上是一个 .NET 应用程序)。

The typical solution to this problem is to specify command line arguments when launching an elevated process (abatishchev's suggestion is one way to do this), so that the launched process knows only to display a certain dialog box, and then quit after this action has been completed. Thus it should hardly be noticeable to the user that a new process has been launched and then exited, and would rather appear as if a new dialog box within the same app has been opened (especially if you some hackery to make the main window of the elevated process a child of the parent process). If you don't need UI for the elevated access, even better.

此问题的典型解决方案是在启动提升的进程时指定命令行参数(abatishchev 的建议是执行此操作的一种方法),以便启动的进程只知道显示某个对话框,然后在此操作完成后退出完全的。因此,用户几乎不会注意到一个新进程已经启动然后退出,而是看起来好像在同一个应用程序中打开了一个新对话框(特别是如果你有一些黑客来制作主窗口)提升进程是父进程的子进程)。如果您不需要用于提升访问权限的 UI,那就更好了。

For a full discussion of UAC on Vista, I recommend you see this very through articleon the subject (code examples are in C++, but I suspect you'll need to use the WinAPI and P/Invoke to do most of the things in C# anyway). Hopefully you now at least see the right approach to take, though designing a UAC compliant program is far from trivial...

有关 Vista 上 UAC 的完整讨论,我建议您通过有关该主题的文章(代码示例使用 C++,但我怀疑您需要使用 WinAPI 和 P/Invoke 来完成 C# 中的大部分事情)反正)。希望你现在至少看到了正确的方法,尽管设计一个符合 UAC 的程序远非微不足道......

回答by Richard

You need a UAC moniker and the code to run elevated as a COM object.

您需要一个 UAC 名称和代码才能作为 COM 对象运行。

See this question.

看到这个问题。

Documentation on MSDN.

MSDN 上的文档。

回答by abatishchev

As it was said there:

正如有人说

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

will run the process as admin to do whatever you need with the registry, but return to your app with the normal privileges.

将以管理员身份运行该进程以使用注册表执行您需要的任何操作,但以正常权限返回到您的应用程序。

回答by FruitBreak

The following MSDN KB article 981778 describes how to 'self-elevate' an application:

以下 MSDN 知识库文章 981778 描述了如何“自我提升”应用程序:

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

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

It contains downloadable samples in Visual C++, Visual C#, Visual Basic.NET.

它包含可下载的 Visual C++、Visual C#、Visual Basic.NET 示例。

This approach gets around the need to start a separate process, but in fact it is the original application that is restarted, running as an elevated user. Nevertheless this may still be very useful in some contexts where it is not practical to duplicate code in a separate executable.

这种方法不需要启动一个单独的进程,但实际上它是重新启动的原始应用程序,以提升的用户身份运行。尽管如此,这在某些情况下仍然非常有用,因为在单独的可执行文件中复制代码是不切实际的。

To remove the elevation, you need to quit the application.

要删除高程,您需要退出应用程序。

回答by SpaceGhost440

I know this is an old post, but this is in response to anyone else who comes across MarcP's suggestion. The msdn post he referenced indeed does restart the applications in all of the code examples. The code samples use the runasverb proposed already in other suggestions.

我知道这是一个旧帖子,但这是对遇到 MarcP 建议的其他人的回应。他引用的 msdn 帖子确实会重新启动所有代码示例中的应用程序。代码示例使用runas已在其他建议中提出的动词。

I downloaded the code to make sure, but this is from the original msdn article:

我下载了代码以确保,但这是来自原始 msdn 文章:

4. Click Yes to approve the elevation. Then, the original application restarts, running as an elevated administrator.
5. Close the application.

4. 单击是以批准提升。然后,原始应用程序重新启动,以提升的管理员身份运行。
5. 关闭应用程序。

回答by Konstantin S.

Perhaps someone comes in handy this simple example:

也许有人会派上用场这个简单的例子:

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

    }
}