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