【问题标题】:elevation demand not working for method in winforms app海拔需求不适用于winforms应用程序中的方法
【发布时间】:2011-08-13 21:23:10
【问题描述】:

我有一个循环安装其他应用程序的 winforms 应用程序。这在 Windows 7 中的管理员帐户上可以正常工作,但我在标准帐户中存在严重问题 - 应用程序需要提升才能写入“Program Files(x86)”文件夹。

因此,我尝试使用以下代码在 winforms c# 应用程序中请求提升特定方法(运行安装程序的方法):

[System.Security.Permissions.PrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

收到错误后,从网上得知,在调用带有上述属性的方法之前,需要这样写:

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

我这样做了,方法仍然抛出以下错误:

请求主体权限失败。

逐步调试通过 SetPrincipalPolicy 行,但是,当它到达具有 Demand 属性的方法时,它只是抛出相同的错误,就好像 SetPrincipalPolicy 从未存在过一样。

我在正确设置 Demand 属性时做错了吗?

提前谢谢你。

稍后编辑:这里要求的是在静默安装应用程序时应该触发提升请求的代码(但不起作用):

 WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
        bool hasAdministrativeRight = principal.IsInRole(WindowsBuiltInRole.Administrator);
        if (!hasAdministrativeRight)
        {
            ProcessStartInfo psi = new ProcessStartInfo(file);
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.UseShellExecute = true;
            psi.Verb = "runas";

            //psi.CreateNoWindow = true;
            psi.Arguments = modifiers;
            try
            {
                using (Process process = Process.Start(psi))
                {
                    process.WaitForExit();
                    if (process.HasExited)
                        return process.ExitCode;
                }
            }
            catch (Win32Exception wex)
            {

            }
        }

我需要的是,如果应用程序在 Windows 标准用户下运行,该进程会弹出一个对话框,询问管理员的用户名和密码。只有上面以编程方式启动的进程应该以管理员身份运行,主应用程序本身可以保持为标准用户。

【问题讨论】:

  • 您需要做一些事情让用户可以输入管理员密码。
  • 谢谢 - 你是不是建议我根本不应该使用上面的代码和属性?另外关于您的评论,我已经阅读了有关要求用户名和密码的同意 UI,但无法找到任何地方如何调用它 - 如果您能指出我的链接,我将不胜感激
  • process.WaitForExit(); 之后process.HasExited 是否应该始终为真?
  • 没错,我认为那是多余的。我将删除 HasExited。

标签: c# principalpermission process-elevation


【解决方案1】:

这不是 UAC 的工作方式。它是基于进程的,当你开始一个新进程时,用户只会得到“请让我弄乱你的机器”提示。程序中嵌入了“我需要用户同意才能弄乱机器,请说是”的正确咒语。您通过this answer 执行的操作。

让基于方法的想法死掉。对程序员不合理,对用户有意义。用户获胜。

【讨论】:

  • 非常感谢您的洞察力。如果您建议我应该包含一个清单以使整个应用程序从一开始就以管理员权限运行 - 这样做不是不安全吗?你能告诉我为什么我不应该基于这种方法吗?请详细说明它是如何不合理的。
  • @Andrei:他并不是说你“不应该”为个别方法这样做,他是说你不能为个别方法这样做。用户帐户控制(或 UAC)是您试图在此处超越的机制,它是基于流程的,而不是基于方法的。至于你应该做什么,你根本不应该这样做。标准应用程序从不需要写入系统目录;他们受到保护是有原因的。是的,授予进程访问这些目录的权限是不安全的。这就是为什么你不应该这样做,除非绝对必要。
  • 感谢您的评论我现在明白了。
【解决方案2】:

您可以强制您的应用始终以管理员身份运行。 This 就是你这样做的方式。但是,不建议您的应用需要管理员权限才能运行。

如果您启动Process 来运行安装程序,您可以查看here 如何以管理员身份运行该进程。

Visual Studio 使用的第三个选项是,当您执行需要管理员权限的操作时,系统会提示您重新启动应用程序,然后它会以管理员身份重新启动应用程序,然后您就可以执行任务了。只需使用第二种方式的代码即可启动您的应用。

您发布的以管理员​​身份运行的方法将检查用户是否为管理员,然后以管理员身份启动该进程。如果用户没有管理员权限,应用程序甚至都不会启动。更好的解决方案是始终尝试以管理员身份运行该进程。然后用户会得到一个带有密码和用户名的 UAC 提示,管理员可以填写。

public static int RunAsAdmin(string fileName)
{

        ProcessStartInfo psi = new ProcessStartInfo(fileName);
        psi.WindowStyle = ProcessWindowStyle.Hidden;
        psi.UseShellExecute = true;
        psi.Verb = "runas";
        psi.Arguments = modifiers;

        try
        {
            using (Process process = Process.Start(psi))
            {
                process.WaitForExit();
                if (process.HasExited)
                    return process.ExitCode;
            }
        }
        catch (Win32Exception wex)
        {

        }

    return 0;
}

【讨论】:

  • 确实,我启动了一个进程来运行安装程序。正如链接所示,我使用了 ProcessStartInfoVerb = runas,但是没有成功 - 我的进程仍然以标准用户身份运行。也许我做错了 - 当我使用 runas 选项时,我是否还必须弹出同意 UI 以询问用户名和密码?谢谢
  • @Andrei 你也在使用 ShellExecute 吗?
  • 我正在使用属性 UseShellExecute = true 根据您提供的链接中的说明(启动进程的链接)。
  • 我已经发布了,请参阅第一篇文章中的编辑。此外,我的意图是不重新启动主应用程序,而只是以管理员身份运行以编程方式创建的进程。主应用程序本身可以作为标准用户运行。谢谢
  • 很高兴听到它奏效了。至于 UAC 是否关闭(甚至可能是不存在 UAC 的旧操作系统),您只需告知用户他需要以管理员身份登录
猜你喜欢
  • 2017-07-13
  • 2015-08-18
  • 2018-01-13
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-05
  • 2019-06-15
  • 1970-01-01
相关资源
最近更新 更多