这个问题适用于Windows Vista操作系统!
我有一个应用程序,通常情况下不需要管理员权限就可以使用。但是有一个活动确实需要管理员权限,但我不想在大多数情况下都以较高的权限启动应用程序,因为用户大部分时间可能甚至不会使用该功能。
我考虑了一种方法,可以在某些事件(例如按下按钮)时提升应用程序的权限。例如:
如果用户单击此按钮,则会提示UAC对话框或请求同意。我应该如何做到这一点?
这个问题适用于Windows Vista操作系统!
我有一个应用程序,通常情况下不需要管理员权限就可以使用。但是有一个活动确实需要管理员权限,但我不想在大多数情况下都以较高的权限启动应用程序,因为用户大部分时间可能甚至不会使用该功能。
我考虑了一种方法,可以在某些事件(例如按下按钮)时提升应用程序的权限。例如:
如果用户单击此按钮,则会提示UAC对话框或请求同意。我应该如何做到这一点?
我不认为可以提升当前正在运行的进程。据我所知,Windows Vista会在启动时授予进程管理员特权。如果您查看使用UAC的各种程序,您应该会发现每次需要执行管理操作时它们实际上都会启动一个单独的进程(任务管理器是其中之一, Paint.NET是另一个,后者实际上是一个.NET应用程序)。
解决此问题的典型方法是在启动提升的进程时指定命令行参数(abatishchev的建议就是其中一种方法),以便启动的进程只知道显示某个对话框,完成此操作后退出。因此,对于用户来说,几乎不会注意到已启动并退出了一个新进程,而是似乎打开了相同应用程序的新对话框(特别是如果您对提升后的进程的主窗口进行一些黑客改造,使其成为父进程的子进程)。如果您不需要提升访问权限的用户界面,那就更好了。
有关Vista上UAC的全面讨论,我建议您参阅这篇非常详细的文章(代码示例是用C++编写的,但我怀疑您无论如何都需要使用WinAPI和P/Invoke来完成大部分C#中的操作)。希望现在您至少知道正确的方法,尽管设计符合UAC标准的程序远非易事...
正如在这里所说:
Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";
这将使用管理员权限运行进程,以便您可以在注册表中执行任何所需操作,但是返回到您的应用程序时将恢复正常权限。
以下是MSDN KB文章981778,介绍了如何“自我提升”应用程序:
http://support.microsoft.com/kb/981778
它包含在Visual C++、Visual C#和Visual Basic.NET中可下载的示例。
这种方法可以避免启动单独的进程,但实际上是以升级的用户身份重新启动原始应用程序。尽管如此,在某些情况下仍然非常有用,例如在不适合将代码复制到单独的可执行文件中的情况下。
要取消提升,需要退出应用程序。
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);
}
}
}
}
runas
动词。