此问题适用于Windows Vista!
我有一个通常无需管理员权限即可运行的应用程序。有一项活动确实需要管理特权,但是当我知道大部分时间用户甚至都不会使用该功能时,我不想以更高的特权启动应用程序本身。
我正在考虑某种方法,通过该方法我可以提高某些事件(例如,按下按钮)的应用程序的特权。例:
如果用户单击此按钮,则系统会提示他UAC对话框或同意。我怎样才能做到这一点?
Answers:
我认为无法提升当前正在运行的流程。据我了解,Windows Vista内置了该功能,该功能可在启动时为进程赋予管理员特权。如果查看使用UAC的各种程序,则应该看到它们每次需要执行管理操作时实际上都会启动一个单独的进程(任务管理器是一个,Paint.NET是另一个,而后者实际上是一个.NET应用程序。 )。
解决此问题的典型方法是在启动提升的进程时指定命令行参数(abatishchev的建议是执行此操作的一种方法),以便启动的进程只知道显示某个对话框,然后在执行此操作后退出完成。因此,用户应该几乎不会注意到已经启动了一个新进程,然后退出了该进程,而是看起来好像是在同一应用程序中打开了一个新对话框(尤其是如果您使用一些黑客工具来创建该新进程的主窗口)提升的流程是父流程的子流程)。如果您不需要UI来提升访问权限,那就更好了。
有关在Vista上进行UAC的完整讨论,我建议您通过关于该主题的文章非常仔细地看到(代码示例在C ++中,但是我怀疑您需要使用WinAPI和P / Invoke来完成C#中的大多数操作无论如何)。希望您现在至少看到正确的方法,尽管设计符合UAC的程序绝非易事...
正如有人说有:
Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";
将以admin身份运行该过程,以执行注册表所需的任何操作,但将以普通权限返回到您的应用。
以下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);
}
}
}
}