如何使用c#显示文件保存到受限位置的UAC提示?

如何使用c#显示文件保存到受限位置的UAC提示?,c#,file-io,permissions,uac,C#,File Io,Permissions,Uac,当用户从我的应用程序保存文件时,他们当前无法保存到受限制的位置(如C:)。我认为这是一个很好的限制,但我想提供一个UAC提示来提升权限并允许用户在限制区域中保存 我已经看到了很多关于这个主题的答案,其中包括使用“runas”生成具有提升权限的新进程。而且,这似乎可以通过模拟其他用户来实现。据我所知,这两种方法都需要用户提供用户凭据 我想做的基本上就是Windows本身的功能。在Windows 7中,当您尝试将文件复制到C:\时(假设您已将UAC设置为其默认级别),会出现以下提示: 使用UAC屏

当用户从我的应用程序保存文件时,他们当前无法保存到受限制的位置(如C:)。我认为这是一个很好的限制,但我想提供一个UAC提示来提升权限并允许用户在限制区域中保存

我已经看到了很多关于这个主题的答案,其中包括使用“runas”生成具有提升权限的新进程。而且,这似乎可以通过模拟其他用户来实现。据我所知,这两种方法都需要用户提供用户凭据

我想做的基本上就是Windows本身的功能。在Windows 7中,当您尝试将文件复制到C:\时(假设您已将UAC设置为其默认级别),会出现以下提示:

使用UAC屏蔽单击“继续”按钮后,文件将复制到C:\中,不提示输入凭据(假设您以管理员权限登录)


如何在应用程序中为管理员用户复制此行为?他们不应该模拟任何其他用户,因为他们已经拥有管理员权限。有人能提供Windows在此过程中所做工作的详细信息吗?他们是否正在生成具有提升权限的新explorer.exe进程?

您需要执行Windows所做的操作。并生成一个新进程,该进程将以提升的权限运行。这里没有捷径。流程启动时分配的令牌决定了流程拥有哪些权限。进程启动后,无法更改该令牌。如果你需要提升,你需要一个新的过程

我已经看到了很多关于这个主题的答案,其中包括使用“runas”生成具有提升权限的新进程。而且,这似乎可以通过模拟其他用户来实现。据我所知,这两种方法都需要用户提供用户凭据

不,不是这样的。如果当前用户不是管理员,则UAC对话框将提示输入具有管理员权限的用户的新凭据。这是一个跨肩UAC对话。另一方面,如果当前用户是管理员,那么他们只需要获得同意对话框。这是安全桌面上显示的对话框,它只要求您单击“继续”

Windows组件可以做的一件事是,您不能在不显示“同意”对话框的情况下启动进程。这种情况仅在Windows 7上发生(不在Vista上),并且仅当您将UAC设置设置为Windows 7中添加的新默认设置时才会发生。这就是为什么Explorer能够显示问题中包含的对话框,然后启动提升的过程来进行复制,而不显示“同意UAC”对话框。只有Windows组件被授予该功能

但底线是,您需要启动一个新的流程,该流程可以在更高的级别上运行。使用
runas
动词是实现这一点的标准方法。

使用比所需权限更多的权限运行应用程序是违反 最小特权原则,并可能具有潜在安全性 脆弱性。为了保护这一点,Windows Vista引入了用户帐户 控制(UAC),通过运行应用程序来保护操作系统 权限降低(作为普通用户),即使是当前用户 以管理员身份登录。越来越多的XP/2K用户也在使用 日常使用的普通用户帐户。阅读UAC,从第一页到第二页 了解UAC

开发人员通常会犯两个错误:

  • 请求最终用户以管理员权限运行应用程序 虽然这不是必须的,但大多数情况下都是因为糟糕的设计 实践。这些应用程序要么吓跑最终用户,要么 可能存在安全漏洞
  • 不要请求最终用户 运行应用程序,但尝试执行以下操作: 需要管理员权限。这些应用程序只是简单地中断 Windows Vista或Windows XP/2K普通用户帐户
可下载的示例代码演示了如何编程 特权/UAC。WPF和Windows窗体示例应用程序都是 假如针对以下场景运行应用程序以查看 区别:

  • 普通用户,Windows XP/Windows Vista:UAC屏蔽图标 显示。单击“保存到C:\”显示“运行方式”对话框,询问 用户输入管理员密码继续
  • 管理员,禁用UAC的Windows XP/Windows Vista:UAC屏蔽图标为 隐藏的。点击“保存到C:\”完成,没有任何对话框
  • 管理员,启用UAC的Windows Vista:UAC屏蔽图标为 显示。单击“保存到C:\”显示对话框,询问用户的 允许继续

调用提升的execute(先测试管理员):

提升执行:

internal static string ElevatedExecute(NameValueCollection parameters)
    {
        string tempFile = Path.GetTempFileName();
        File.WriteAllText(tempFile, ConstructQueryString(parameters));

        try
        {
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.UseShellExecute = true;
            startInfo.WorkingDirectory = Environment.CurrentDirectory;
            Uri uri = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase);
            startInfo.FileName = uri.LocalPath;
            startInfo.Arguments = "\"" + tempFile + "\"";
            startInfo.Verb = "runas";
            Process p = Process.Start(startInfo);
            p.WaitForExit();
            return File.ReadAllText(tempFile);
        }
        catch (Win32Exception exception)
        {
            return exception.Message;
        }
        finally
        {
            File.Delete(tempFile);
        }
    }

有限选项,仅在移动、重命名、复制和删除文件时有用:

如果试图通过此功能执行文件操作,Windows将向用户提供提升提示

注意:这有一些缺点:

  • 这仅适用于移动、重命名、复制和删除。以这种方式保存新文件需要保存到临时目录,然后将其移动到所需位置。这并不能解决“保存文件”对话框不允许您选择受UAC保护的位置作为目标的问题
  • 如果目标目录不存在(对于移动或复制),SHFileOperation可以提示用户是否应该创建目标目录。但是,它不会要求提升权限来执行此操作,因此在受UAC保护的位置下会失败。解决方法是在临时位置手动创建不存在的目录,然后将它们移动/复制到目标位置。这将提供
    internal static string ElevatedExecute(NameValueCollection parameters)
        {
            string tempFile = Path.GetTempFileName();
            File.WriteAllText(tempFile, ConstructQueryString(parameters));
    
            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.UseShellExecute = true;
                startInfo.WorkingDirectory = Environment.CurrentDirectory;
                Uri uri = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase);
                startInfo.FileName = uri.LocalPath;
                startInfo.Arguments = "\"" + tempFile + "\"";
                startInfo.Verb = "runas";
                Process p = Process.Start(startInfo);
                p.WaitForExit();
                return File.ReadAllText(tempFile);
            }
            catch (Win32Exception exception)
            {
                return exception.Message;
            }
            finally
            {
                File.Delete(tempFile);
            }
        }