这个问题适用于Windows Vista!
我有一个通常在没有管理权限的情况下工作的应用程序。有一项活动确实需要管理权限,但是当我知道大多数时候用户甚至不会使用该功能时,我不想以更高的权限启动应用程序本身。
我正在考虑某种方法,通过该方法我可以在某些事件(例如按下按钮)上提升应用程序的权限。例子:
如果用户单击此按钮,则会提示他使用 UAC 对话框或同意。我怎样才能做到这一点?
这个问题适用于Windows Vista!
我有一个通常在没有管理权限的情况下工作的应用程序。有一项活动确实需要管理权限,但是当我知道大多数时候用户甚至不会使用该功能时,我不想以更高的权限启动应用程序本身。
我正在考虑某种方法,通过该方法我可以在某些事件(例如按下按钮)上提升应用程序的权限。例子:
如果用户单击此按钮,则会提示他使用 UAC 对话框或同意。我怎样才能做到这一点?
我不相信有可能提升当前正在运行的进程。据我了解,它内置于 Windows Vista 中,在启动时授予进程管理员权限。如果您查看使用 UAC 的各种程序,您应该看到它们实际上在每次需要执行管理操作时启动一个单独的进程(任务管理器是一个,Paint.NET 是另一个,后者实际上是一个 .NET 应用程序)。
此问题的典型解决方案是在启动提升的进程时指定命令行参数(abatishchev 的建议是这样做的一种方法),以便启动的进程只知道显示某个对话框,然后在执行此操作后退出完全的。因此,用户几乎不会注意到一个新进程已经启动然后退出,并且宁愿看起来好像同一个应用程序中的一个新对话框已经打开(特别是如果你有一些黑客来制作主窗口的主窗口)提升的进程是父进程的子进程)。如果您不需要 UI 来进行提升访问,那就更好了。
有关 Vista 上 UAC 的完整讨论,我建议您通过有关该主题的文章(代码示例使用 C++,但我怀疑您需要使用 WinAPI 和 P/Invoke 来完成 C# 中的大部分操作)反正)。希望您现在至少看到了正确的方法,尽管设计一个符合 UAC 的程序远非微不足道......
正如那里所说:
Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";
将以管理员身份运行该过程以对注册表执行您需要的任何操作,但以正常权限返回您的应用程序。
以下 MSDN 知识库文章 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);
}
}
}
}
我知道这是一篇旧帖子,但这是对遇到 MarcP 建议的任何其他人的回应。他引用的 msdn 帖子确实重新启动了所有代码示例中的应用程序。代码示例使用runas
其他建议中已经提出的动词。
我下载了代码以确保,但这是来自原始 msdn 文章:
4. 单击“是”批准提升。然后,原始应用程序重新启动,以提升的管理员身份运行。
5. 关闭应用程序。