给应用程序提升的UAC权限

13

我的应用程序需要UAC提升。

我已经有了可以让我进行提升的代码,但是应用程序会打开两次,这是一个问题。

这是Form1的代码:

public Form1()
{
    InitializeComponent();

    WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
    bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator);           

    if (!hasAdministrativeRight)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.UseShellExecute = true;
        startInfo.WorkingDirectory = Environment.CurrentDirectory;
        startInfo.FileName = Application.ExecutablePath;
        startInfo.Verb = "runas";
        
        try
        {
            Process p = Process.Start(startInfo);
        }
        catch (System.ComponentModel.Win32Exception ex)
        {
            return;
        }
    }
}

这是programs.cs的代码:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

通过调试,我发现它首先执行

Process p = Process.Start(startInfo);

它打开应用程序的UAC权限弹窗,然后打开应用程序

但接下来它进入

Application.Run(new Form1());

在main()中再次打开了应用程序。

我不想让它再次打开此应用程序。

我是新手,所以我想问:我有做错什么吗?是否需要在打开UAC后关闭它?


所以这对我来说很好用...因为我是从VS运行的,它要求我重新启动应用程序,我就这样做了。然后它要求我在我的计算机上进行更改...但我在信息中看到这些更改只会影响当前应用程序。所以我允许了它。现在这个应用程序具有提升的UAC权限。我运行了另一个应用程序,发现我不是管理员,这是期望的。 - user175084
4个回答

32

我试着使用这个,但现在当我从VS运行应用程序时,它要求我“以不同的凭据重新启动”,如果我这样做,它会想要对计算机进行更改..?这安全吗?我的意思是,我并不想永久地这样做,只是为了这个应用程序。 - user175084
5
该应用程序需要管理员权限,就像您要求的那样。 - J. Steen
4
因为您没有以提升的进程运行 Visual Studio,很可能是这个原因。由于您正在从 Visual Studio 启动应用程序,因此需要提升 Visual Studio 权限才能启动提升的进程。 - J. Steen
1
我们在这里帮忙,不用担心。=) - J. Steen
这是一个非常好的答案,其中包含了设置应用程序清单以获取提升权限的具体指令。链接 - Scott

5

将WindowsPrincipal代码从您的窗体移动到Program.cs中,就像下面的示例一样。这将在启动任何窗体之前提示用户获取UAC权限,并且仅在UAC权限被授予时才启动窗体。

        static void Main()
        {
            WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator);

            if (!hasAdministrativeRight)
            {
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.UseShellExecute = true;
                startInfo.WorkingDirectory = Environment.CurrentDirectory;
                startInfo.FileName = Application.ExecutablePath;
                startInfo.Verb = "runas";
                try
                {
                    Process p = Process.Start(startInfo);
                    Application.Exit();
                }
                catch (System.ComponentModel.Win32Exception ex)
                {
                    MessageBox.Show("This utility requires elevated priviledges to complete correctly.", "Error: UAC Authorisation Required", MessageBoxButtons.OK);
//                    Debug.Print(ex.Message);
                    return;
                }
            }
            else
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }

3

提升权限总是会启动一个新的进程。除非一开始就以管理员权限设置应用程序,否则没有其他方法可以避免这种情况。您可以在提升进程启动后立即结束应用程序,这样您只有一个正在运行的应用程序。

这种方案适用于仅需要某些功能部分提升权限的应用程序 - 例如自动更新安装程序需要访问“Program Files”的应用程序 - 而不是需要始终具有管理员访问权限的应用程序。


所以我在 Process p = Process.Start(startInfo); 之后添加了 this.Close(); 和 Application.Exit();,但是在 Application.Run(new Form1()); 处出现了错误信息 "无法启动已释放的应用程序"? - user175084
1
我建议您也检查其他答案,以寻找实现您想要的功能的替代方法。 - J. Steen

3

这篇文章提供了一种更好的方法,当您的应用程序从一开始就需要管理员权限时使用。


我试着使用这个,但是现在当我从VS运行应用时,它要求我“以不同的凭据重新启动”,如果我这样做,它就想要对计算机进行更改。这安全吗?我的意思是我不想永久地这样做,只是为了这个应用程序。 - user175084
2
安全是相对的。显然,您的应用程序需要提升的权限,因此正在执行某些固有的不安全操作。将清单添加到您的应用程序仅会影响您正在处理的应用程序,因此不会影响其他项目,除非您也在这些应用程序中包含清单。我不会一直以提升的特权运行VS,而且我无法真正解决这可能为您打开的漏洞问题,因为其中一些将取决于插件和其他因素。 - Bueller
您可以使用互联网档案馆 Wayback Machine 查看 该文章 的存档版本。 - Scott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接