【发布时间】:2011-02-03 04:11:31
【问题描述】:
我们有一个用 C++ 和 .NET 编写的应用程序,它为 Program Files 文件夹中的所有用户安装。此应用程序会下载自身的新版本(作为 MSI 安装程序)并生成新的安装程序进程来替换自身。
目前的安装过程:
- 将安装管理器应用程序(C#、.NET 2.0)复制到临时目录。称其为“经理”
- Manager 使用提升的 privs per this article 执行。
- 原始应用程序退出。
- 管理器生成 MSI 安装程序(具有提升的权限,因为副本已提升)
- Manager 生成新版本的应用程序。
错误:
新安装的应用在提升状态下运行。这会导致我不会在此列举的问题。
理想情况下,新安装的应用程序的启动将在原始用户的权限下运行。
我不知道如何在提升后将应用降级为标准用户。
一个不雅的hack:
(是的,是的,这整个过程无论如何都不优雅)
- 将安装管理器复制到临时目录
- 使用标准用户权限运行安装管理器。让我们将此实例称为“LowlyManager”。
- 原始应用程序退出。
- LowlyManager再次生成应用程序,这次是提升权限。让我们将此实例命名为“UpperManagement”
- UpperManagement 生成安装程序
- UpperManagement 正常退出,返回安装程序的退出代码。
- LowlyManager 解释来自 UpperManagement 的错误代码,并生成新安装的应用程序。这次作为原始调用者。
有更好的方法吗?
(我在这些步骤之前和之后遗漏了许多其他细节,这些步骤使用户的流程更顺畅,但这应该足以理解我要解决的问题的核心。)
其他要求:
- 我们无法安装为每用户应用程序
- 如果 UAC 只是询问“您确定要允许此操作吗?”,则不应向用户显示身份验证对话框。我认为这可能会扼杀使用 WindowsImpersonationContext 的解决方案,但我不确定。
- 系统需要在 XP、Vista 和 Windows 7 上运行(即使 XP 有单独的进程)。
【问题讨论】:
-
您是如何创建 MSI 的?为什么你的“经理”需要被提升?通常,Windows 安装程序会为您处理提升,您无需使用提升来启动 MSI。
-
“不应向用户显示身份验证对话框”:没有办法获得用户同意(当然,除非禁用 UAC)。这就是 UAC 的全部意义所在。
-
回复:“通常,Windows 安装程序将处理提升...”我们在安装之前提升,因为我们有一个服务正在运行,需要在安装之前停止。如果我们不手动停止服务,那么 Windows 安装程序引擎会抱怨服务(即使 MSI 中有代码在安装之前停止服务)。本质上,我们正在尝试简化安装,这样用户就不会被一堆不必要的对话所困扰。 - 布赖恩
-
Re:“没有办法获得用户同意...”:是的...但是... Vista 和 Win 7 以多种方式请求同意。对于具有管理员提升权限的用户来说,发生的情况是“你想让(应用程序)对你的系统进行更改”。用户的响应是一个简单的是/否答案。如果您没有提升权限,您会看到一个用户名/密码对话框。据我所知,使用 WindowsImpersonationContext 需要明确的凭据,这意味着即使在 UAC 只会询问“是/否”问题的情况下,我也必须提示输入用户名/密码。这是不可接受的。
-
我不知道您使用什么工具来创建您的 MSI,但在 WiX 中似乎可以(虽然我自己没有尝试过)在要求提升后卸载/关闭正在运行的应用程序(见n2.nabble.com/…)
标签: c# windows-installer uac elevation