“每用户”安装如何以及为何设法写入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调用(例如MsiEnumProductsExMsiConfigureProductEx)读取或写入它们。 (可以肯定的是,将后者称为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

即使具有管理员权限也无法读取/写入 HKLM 注册表项和值

何时以及为何调用 updateConstraints?

检测注册表虚拟化

为何要通过Kibana展示promethues的数据以及如何去做

innosetup如何往注册表写入多条