Windows应用程序注册表设置和指南

时间:2017-10-19 11:00:14

标签: wix windows-installer registry

由于我一直在学习WiX来编写安装程序,我从文档和教程中学到了很多东西,如何在安装过程中设置程序以及设置或读取注册表值。但是,所述文档和教程中的注册表设置无需解释此类设置的要求即可完成。

作为一个具体示例,我有一个WiX安装程序,用于将InstallScope设置为perMachine的简单应用程序。我想在我的WiX安装程序中添加一个“注册用户”对话框。我找到了一个允许用户输入其姓名,组织和注册密钥的示例。它们分别设置为WiX预定义属性:USERNAME,COMPANYNAME和PIDKEY。在验证这些内容后,WiX会将这些内容写入以下注册表文件夹:

HKLM > Software > Microsoft > Windows > CurrentVersion > Installer > UserData > S-1-5-18 > Products > {GUID} > InstallProperties

我一直在做很多研究,试图找到以下问题的答案,但却未能找到答案。

  1. 安装最简单的Windows应用程序时,需要设置哪些注册表项的最低要求(或至少是Microsoft的最低准则)是什么?我知道这取决于安装是针对所有用户(机器)还是特定用户,因此会有两个不同的答案。

  2. 简单应用程序信息应该保存在注册表中的标准位置在哪里?

  3. 为了满足#1的指导方针/要求,WiX总是在没有显式XML条目的情况下创建的注册表设置是什么?

  4. 设置某些注册表项后,如上面给出的示例,应用程序如何使用注册表API正确找到它们?具体来说,例如,如果一旦安装,我希望我的应用程序能够读取注册的用户信息,它是否真的必须知道并打开如上所示的整个密钥,或者是否有一个Windows API调用处理其中的一部分

  5. 我确实在一篇名为Application Registration的文章中找到了MSDN中一些看起来很有希望的信息,但我无法将该文章的细节与WiX与安装注册表的内容联系起来。具体来说,例如,他们建议使用HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER > SOFTWARE > Microsoft > Windows > CurrentVersion > App Paths > ...,但在我的系统(运行Windows 10)上,密钥甚至不存在。所以其他应用甚至没有使用它。这导致回到我的问题#1。

2 个答案:

答案 0 :(得分:2)

那些" WiX预定义属性:USERNAME,COMPANYNAME和PIDKEY"实际上是Windows安装程序属性,其中包含MSDN中的文档,例如PIDKEY:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370826(v=vs.85).aspx

我没有看到与他们相关的问题,但他们是安装期间要使用的Windows Installer属性。用户名写入注册表的事实是文档的实现细节:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa372385(v=vs.85).aspx

声明如果未自动设置,则会使用之前保存的值。

WiX生成用于安装的MSI文件,因此其许多属性和数据项直接转换为MSI文件或Windows Installer属性中的某些内容。 与Windows Installer的标准和最佳实践有关的大部分信息都在这里:

https://msdn.microsoft.com/en-gb/library/bb204770.aspx

as" Windows Installer最佳实践"它包含指向Windows Installer徽标要求的链接:

https://msdn.microsoft.com/en-gb/library/aa372825.aspx

所有这些都讨论了安装和应用程序的最佳实践,所以这真的只是一个"链接"回答这部分问题,因为那里有很多。

关于#3,您可能意味着Windows Installer,而不是WiX。但无论哪种方式都无关紧要,因为它的实施细节。有MSI API - 请参阅下面的评论。一个示例:如果Windows将有关所有安装程序组件的信息写入注册表,则它不重要,因为MsiEnumComponents()将枚举系统上的所有组件,MsiEnumClients()将枚举拥有它们的产品,MsiGetComponentPath(),其中安装了组件等等。

从您的问题中不清楚注册的用户信息是什么"是的,除非你的意思是USERNAME。您想知道谁安装了该产品吗?如果是这样,USERNAME不是最佳选择,因为它不必是用户帐户 - 它只是一个名称。通常,有这样的一切API,不需要读取注册表。 MsiGetProductInfoEx()将为您提供特定用户的产品信息。 MsiEnumProductsEx()将枚举所有产品以及安装它们的用户。

正如文档所说,PIDKEY是未经验证的产品ID。它成为ProductID属性,可以使用MsiGetProductInfo(..ProductCode ...," ProductID",...)从应用程序中检索,并注意到你得到" RegCompany"和" RegOwner"这是你提到的其他人。

答案 1 :(得分:0)

我认为Phil回答了你的大多数问题,让我看看我是否可以在问题4 中添加一些东西。对于问题1和3 的一些初步答案。 问题2 - 或许可以看到下面的注册表位置列表。

如果我理解正确,您想要访问" 标准属性"在安装过程中通过适当的API写入注册表,因此您不需要直接阅读您所说的注册表位置。实质上,您希望通过正确的API。

感谢上帝有人努力解决这个问题,因为有太多人直接破解了注册表。永远不要走那条路。

关于问题2 。 Windows Installer数据库存储在多个注册表位置,以下是其中一些:

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer
  • HKCR\Installer
  • HKCU\Software\Microsoft\Installer
  • 如果您有任何项目,请在此处添加项目,我知道这里有更多地点

这些密钥下的所有内容实际上都是菲尔解释过的实现细节。这里什么也不应该写,因为你怀疑什么都不应该从这里读到"手动" (直接地)。

也许我误解了这个问题? 也许您想知道在哪里可靠地存储您自己的自定义MSI属性?如果你问我,我会将它们存储在:

  • HKLM \ Software \ YourCompany \ YourApp \ MajorVersion [此处的值列表]
  • HKCU \ Software \ YourCompany \ YourApp \ MajorVersion [此处的值列表]

您可以创建任意数量的此类自定义属性,只需在WiX中使用注册表元素即可将该属性的值写入注册表。您在注册表标记中将值称为[PROPERTYNAME],以将属性的值写入指定的注册表项/值。

然后,您的应用程序可以使用标准的Win32,.NET甚至COM API轻松读回信息。

现在第4期 - 从注册表中检索内置MSI属性值

如果要从注册表中检索标准的内置MSI属性(换句话说,不是您自己的自定义属性),您应该通过正确的API,因为注册表中的位置将是&# 34; 移动目标&#34;当您使用MSI主要升级升级您的应用程序时(产品代码是注册表路径的一部分,并使用主要升级产品代码将更改) - 所以不要直接从以下子键读取:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18。< / p>

因此,为了直接访问 MSI数据库文件中的信息(从实际的MSI数据库文件)或从系统上已安装的软件包中检索信息(从注册表中) ),您可以使用MSI API - 换句话说,Windows Installer Win32 API,它还提供了一个可从脚本语言访问的COM层。所以从本质上说你有:

  1. C / C ++样式安装程序函数(通常在C ++中使用的Win32调用)
  2. COM自动化
    • 基本上是安装程序功能顶部的COM层
    • 您可以使用 VBScript JavaScript 或任何Active Scripting语言来访问它。
  3. 第三种选择: DTF - 围绕Win32 MSI SDK的.NET包装器(详情如下,on serverfault.com)。允许您从.NET语言(如C#)高效访问MSI SDK,无需任何COM Interop clunk。
  4. MSI SDK :您有 msi.chm 帮助文件随时可用吗? 这是MSI圣经。这是MSI所有东西的一站式位置(您可能已经拥有它,我认为它已经安装了WiX) - 您将在此处找到用于访问MSI API的文档。如果您没有该文件,但安装了Visual Studio,只需搜索它并为您的桌面添加快捷方式或类似的东西。或者在WiX安装文件夹中查找。您还可以找到信息online on MSDN,但使用本地文件要快得多。而且你会感觉到完整性&#34;当你处理文件而不是&#34;无尽的网络&#34;。

    作为MSI SDK的一部分,有一个示例COM自动化VBScript,它显示了如何检索已安装的MSI包的产品信息(产品属性)。它被称为 wilstprd.vbs - 有a whole family of such sample VBScript for various MSI related tasks。我几乎可以肯定这不包含在WiX中(也许它应该是?),它不是MSI SDK帮助文件msi.chm的一部分。

    如果安装了Visual Studio,还应安装Windows SDK。只需搜索 wilstprd.vbs ,您就应该在多个位置找到它(x86,x64版本 - 没有文件内容差异)。如果您有默认安装,则可以在%SystemDrive%\Program Files (x86)\Windows Kits开始搜索。

    您可以像这样运行此脚本(使用cmd.exepowershell.exe):

    cscript .\wilstprd.vbs "{A645BC30-D32A-408B-B964-C190C9056D7A}"
    

    这将从已安装的MSI生成属性值列表:

    Powershell show MSI properties

    从注册表数据库中检索MSI属性所需的所有信息都应该在该示例文件(wilstprd.vbs)中,但下面是我自己修改后的一个快速模型可用(我认为这是Phil改编的样本)。它只是一个没有任何错误处理的最小样本。它只是将一些核心MSI属性输出到所有已安装的MSI文件的文本文件中。

    复制脚本并粘贴到桌面上的* .vbs文件中,然后双击尝试运行它。您的桌面必须是可写的,或者您可以使用任何其他可写位置。输出为msiinfo.csv(显然在Excel,记事本或任何其他查看器中以逗号分隔值打开)。这是一个糟糕的脚本,它没有错误处理,并且它不会逃避属性值中的任何嵌入式逗号,但它只是作为MSI API的一个简短示例:

    Set fso = CreateObject("Scripting.FileSystemObject")
    Set output = fso.CreateTextFile("msiinfo.csv", True)
    Set installer = CreateObject("WindowsInstaller.Installer")
    
    On Error Resume Next ' Ignore all errors
    
    output.writeline ("Product Code,Product Name,Version") ' Column headers
    
    ' Output 3 core built-in MSI properties for each installed MSI package
    For Each product In installer.ProductsEx("", "", 7)
       productcode = product.ProductCode
       name = product.InstallProperty("ProductName")
       version=product.InstallProperty("VersionString")
       output.writeline (productcode & ", " & name & ", " & version)
    Next
    
    output.Close
    
    MsgBox "Export done, please open msiinfo.csv"
    

    最后,问题1&amp; 3 - 注册所需的最低资产是多少?诚实的回答是我不知道。我不确定。

    这只是一个试探性的答案,但MSI SDK示例脚本 wilstprd.vbs 会检索以下MSI属性。我认为这意味着它们总是被写入MSI数据库 - 其中一些似乎总是返回一个空字符串。因此,它们是内置的MSI属性

    ProductCodeLanguageProductNamePackageCodeTransformsAssignmentTypePackageNameInstalledProductNameVersionStringRegCompanyRegOwnerProductIDProductIconInstallLocationInstallSourceInstallDate,{ {1}},PublisherLocalPackageHelpLinkHelpTelephoneURLInfoAbout

    其中一些属性至关重要,来自MSI数据库文件本身,例如Product Code,ProductName,Language,PackageCode,VersionString。我不认为可以在没有设置这些值的情况下安装MSI。据我所知,所有这些都应该由WiX编译包设置。

    根据msiexec.exe(命令行)执行安装的方式设置其他属性。这包括Transforms(在安装命令行中应用的转换列表),AssignmentType(无论是每台机器还是每个用户安装MSI),InstallSource(已安装的MSI的源位置),InstallDate(以安装时的字符串形式的短日期时间或修改已执行)。

    转换是在安装时应用于MSI的小数据库片段。它们用于修改原始MSI而不更改原始文件。 Here is a description of using transforms and applying them and / or property values at the command line

    最后,一些属性似乎经常丢失并返回空白,例如RegCompany,RegOwner,HelpLink,HelpTelephone,URLInfoAbout,URLUpdateInfo。这些可能需要手动添加到我认为的属性表中(或者更确切地说,作为WiX源文件中的属性添加)。

    完全偏离主题,但你提出所有正确的问题,我认为你只需要正确的信息来源(而不是我过度解释事情)。

    如果这是一个糟糕的礼仪我道歉 - 但这应该包括各种可能真正帮助人们的来源,如果他们在这里找不到答案的话。 如果不合适,我很乐意将其删除

    使用新技术找到我的脚时,我总是尝试使用帮助文件找到 SDK信息,并希望有基本的样本。然后我寻找真实世界的样本,最后我寻找信息来源和博客来征求意见和阅读(实质上弄清楚什么不该做,不仅仅是什么去做)。以下是我最喜欢的MSI / WiX信息来源 - 自助链接:

    明确的消息来源&#34;圣经&#34;帮助文件

    • MSI SDK URLUpdateInfo
    • WiX帮助文件msi.chm
    • DTF帮助文件(包含在WiX中):WiX.chmDTF.chm

    DTF是整个MSI API的.NET包装器。它设计得非常好,可以使用C#和其他.NET语言轻松访问MSI文件和MSI信息。它是作为WiX的一部分安装的。

    在线WiX资源

    查找常规部署信息

    提出部署问题

    <强>博客

    我认为这应该是一个平衡的列表&#34;部署资源,但许多可能已被遗忘。