我们在这里似乎有两个不同的问题:
- 我应该如何处理需要提升权限的操作?
- 如果我使用单独的进程,我应该如何告诉其他进程该怎么做?
这是我试图回答的问题:
- 从这个 SO 问题:Windows 7 and Vista UAC - Programmatically requesting elevation in C# 看来,解决方案正如您在问题中建议的那样(运行另一个进程并让它在启动时请求提升)是“正确答案”
- 至于告诉其他进程该做什么,下面是我尝试的方法:
我将首先将需要提升权限的每个操作拆分给他们自己的“帮助”程序。这些帮助程序将只执行一个操作,通过命令行获取参数。
例如,假设您的程序需要停止/启动服务,我会编写一个名为 servicecontroller 的小帮助程序(实际上您可能希望使用 net 命令),它采用类似于以下的命令行参数这个:
servicecontroller stop MyCoolService
servicecontroller start MyCoolService
这些参数将由“主”程序构建并在点击“确定”后传递。
上述解决方案存在几个问题,您可能关心也可能不关心:
- 您正在命令行上传递参数,这很容易被嗅探到
- 您受到ProcessStartInfo.Argument + 程序路径长度的限制(来自 MSDN:添加到进程完整路径长度的参数长度必须小于 2080。 )
- 将信息传回给您可能有点棘手(如果您需要这个)
更多的谷歌搜索揭示了'DevZest' 的这篇博客文章,它基本上推荐了我上面描述的内容。祝你好运!
编辑基于 cmets 中提出的其他问题:
- 您是否建议在需要执行提升的操作时启动单独的可执行文件或同一个可执行文件?
- (我正在阅读这篇文章的字里行间)我应该多久提示用户执行这些操作?
我不知道你在这里做什么是我的看法:
- 我个人会为这些操作中的每一个提供单独的可执行文件,但不知道您正在尝试做什么,因此很难进行此调用。一般来说,虽然您似乎希望每个提升的操作都有一个单独的过程。
- 我对您的第二个示例感到有些困惑,在不知道您要做什么的情况下,我将仅根据您在评论中提供的示例进行操作。
在文件管理器示例中,我将执行资源管理器所做的操作,并首先遍历每个目标目录,以确定是否有任何目标位置需要提升权限才能复制到。如果他们这样做,我会标记一个标志,指示该操作需要以管理员身份执行,提示用户,然后以管理员身份执行整个操作。
至于文本编辑器示例,我会做与上面类似的事情,当用户给你一个目标目录时,检查你是否有对该位置的写访问权,如果没有通知用户他们正在保存到一个位置需要提升,将他们的工作保存到可写位置(您的程序的 APPDATA 可能是一个好地方,甚至 TEMP),然后启动请求提升的复制过程,如果用户取消 UAC 对话框,请确保您捕获此取消并删除临时文件。
如果您发现您的程序在程序生命周期内需要多次请求提升(Readas:1 或 2 个极端案例),我会劝阻您不要保留提升的工作进程,那么我会质疑为什么它未标记为始终升高。我喜欢遵循“最少意外”规则,当我授予您提升的权限时,我希望您只执行请求它的操作,而不是继续通过第一个请求执行需要提升的操作。
话虽如此,没有什么可以阻止您执行上述操作,一旦您让某个进程获得更高的权限,他就可以邀请他的所有伙伴。基于您希望保持提升进程的愿望,为什么不保存程序的当前状态,并以提升的权限重新启动程序并恢复状态?在我看来,这与让工作进程始终处于提升状态是一样的。
如果您能告诉我们更多关于您正在尝试做什么的信息,我们或许能够找到更好的方法来实现这一目标,而不必遇到 UAC 问题。虽然有一些很好的理由写入受 UAC 保护的区域,但在大多数情况下,程序不需要写入/访问这些位置。