“每用户”安装如何以及为何设法写入HKLM?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“每用户”安装如何以及为何设法写入HKLM?相关的知识,希望对你有一定的参考价值。
“每用户”安装模式似乎有其不可思议的作用。
我们的应用程序具有不使用insaller的自动更新程序,我想更新“添加/删除程序”窗口中显示的应用程序版本。我很惊讶设置信息(以及版本)实际上存储在
中 HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ProductId
和
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\SId\Products\ProductId
所以我的问题是:安装程序如何在不要求提升权限的情况下写到那里?为什么每个用户的安装都在HKLM中注册,尤其是在第一个入口,它看起来根本与任何特定用户都不相关?
其他随之而来但更实际的问题是如何从代码中进行更新(当然,没有提升)?
Windows Installer在多个上下文中运行。存在调用它的上下文(通常是受限用户,或者至少是Administrator组中用户的非管理员变体),以及服务上下文。后者几乎可以完全访问该计算机,但是可以在模拟原始调用程序的同时完成其大部分工作。定制操作和内置操作可以访问服务上下文(如果UAC或早期的广告允许),则该服务始终可以使用它。
所以这就是它的访问方式。但是,为什么要使用此访问权限在HKLM中存储有关产品的信息?虽然您可能熟悉SharedDllRefCount,但这仅用于与其他解决方案进行互操作。相反,Windows Installer自己跟踪类似或扩展的信息,并且它需要访问其管理的所有安装的所有实例,即使这些实例是按用户且该用户未登录也是如此。当用户未登录时,则无法可靠地访问其HKCU密钥,因此Windows Installer无法使用该位置。因此,它使用HKLM。
您可能还想知道为什么它必须有权访问每个用户安装的数据。简而言之,因为它无法确定安装是否真正针对每个用户。尤其是在Windows 7和MSIINSTALLPERUSER
之前,但即使现在,也不能轻易确定安装是否可以写入共享计算机位置。因此,我猜他们甚至没有尝试确定这一点。毕竟,当简单方法足够时,为什么要实现困难或脆弱的功能?
那么您如何更新它?通过安装更新的.msi文件并让Windows Installer服务为您更新它;这些注册表项是允许Microsoft随时更改的实现详细信息。您仅应通过Msi * API调用(例如MsiEnumProductsEx或MsiConfigureProductEx)读取或写入它们。 (可以肯定的是,将后者称为API来写入这些值有些麻烦,但这是为数不多的有效方法之一。)即使数据存储在HKCU中,答案的这一部分也没有什么不同。
Windows可以写入该卸载位置,因为它是Windows。安全限制适用于您的操作,而不是Windows的操作。毕竟,它是OS,可以满足其要求。如果非高架安装无法在“程序和功能”中创建条目,这将非常奇怪。这些注册表项实际上不在MSI文件中。
严格来说,每个用户都不是问题。如果需要,可以提高每个用户的安装量,尽管通常的约定是不提高每个用户的安装量。如果您的更新程序写入了卸载密钥,则它将需要提升。
附带说明:如果您的自动更新程序正在更新或替换Windows Installer安装的文件,则您违反了规则。仅应使用基于MSI的解决方案进行更新。问题是Windows知道(例如)您安装的每个版本文件的文件版本。如果用户进行了修复(或者由于某种原因而进行了修复),则可能会发现Windows想要将文件还原到最初安装的版本。同样,如果进行补丁程序或重大升级,则Windows将不会知道磁盘上的版本与注册版本不匹配时是否需要更新文件,因此可能会要求原始MSI文件来还原它们。
我已经使用以下逻辑来更新版本号,并且它正确地反映在控制面板中->添加删除程序
using (var uninstallSubKey = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",true))
if (uninstallSubKey != null)
var subKeyNames = uninstallSubKey.GetSubKeyNames();
foreach (var subKeyName in subKeyNames)
using (var subKey = uninstallSubKey.OpenSubKey(subKeyName, writable: true))
if (subKey?.GetValue("DisplayName") as string == "YOUR_PRODUCT_NAME")
subKey.SetValue("DisplayVersion", "YOUR_NEW_VERSION",
RegistryValueKind.String);
break;
感谢与问候Rajasekhar
以上是关于“每用户”安装如何以及为何设法写入HKLM?的主要内容,如果未能解决你的问题,请参考以下文章
halcon安装提示could not write updated path to HKLM