升级时保留注册表设置

Har*_*wok 1 registry installer windows-installer wix wix3

我正在使用WiX 3.0.我正在尝试在升级时预先设置所有注册表设置.

我找到了以下链接 http://www.mail-archive.com/wix-users@lists.sourceforge.net/msg28844.html

我更喜欢使用Property和RegistrySearch方法而不是自定义操作方法,因为我觉得它看起来更简单.

不幸的是,这种方法对我来说效果不佳.我的项目有一些DWORD和SZ类型的注册表值.对于所有DWORD类型的注册表值,它在前面附加一个#.我检查了WiX推荐手册.这就是RegistrySearch的工作方式.

因此,升级后,结果是我的所有DWORD类型注册表都更改为SZ.该值看起来相同,只是前面附加了#.例如,我在注册表值"LogLevel"中获得值为DWORD的值2.升级后,我在注册表值"LogLevel"中获得值"#2",类型为SZ在同一位置.

这是代码片段

<Property Id='LOG_LEVEL' Value='Information'>
  <RegistrySearch Id='LogLevelRegistry' Type='raw' Root='HKLM' Key='Software\Company\Product' Name='LogLevel' Win64='$(var.Win64)'/>
</Property>

<Component Id="RegistryKey">
    <RegistryKey Root='HKLM' Key='Software\Company\Product' Action='createAndRemoveOnUninstall'>
      <RegistryValue Type='int' Name='LogLevel' Value='[LOG_LEVEL]'/>
    </RegistryKey>
</Component>
Run Code Online (Sandbox Code Playgroud)

我想知道是否有任何字符串函数可以帮助我修复LOG_LEVEL属性中的"#"然后再放回去.或者在升级时是否有更智能的方法来保留注册表项?我应该采用自定义操作方法吗?

Har*_*wok 6

我终于得到了RegistrySearch方法.我希望这可能会对未来的其他人有所帮助.

我检查了MSI文档.Registry表实际上不包含名为type的列.相反,它以奇怪的方式存储Value,以便MSI知道它应该创建什么类型的注册表值.在我的例子中,我想创建一个DWORD类型的注册表值.如果我想将数值1放入注册表值,则该值应存储在Registry表中#1.这是Registry表的链接

那么,为什么Wix RegistryValue有一个强制属性Type?我想这是因为Wix试图对你很好.如果将类型标记为int,则只需在value属性中输入"1"即可.您不需要记住您必须输入"#1"而不是"1".编译Wix源代码时,编译器将为您执行脏工作并将"1"转换为"#1".

同样,RegistrySearch是直接映射到MSI数据库表RegLocator.它返回#1给我,因为我的注册表值类型是DWORD.这次Wix没有为我做翻译太糟糕了.以下代码将表中的原始数据返回给我.所以,我的属性LOG_LEVEL存储#1而不是1.

<Property Id='LOG_LEVEL' Value='3'>
  <RegistrySearch Id='LogLevelRegistry' Type='raw' Root='HKLM' Key='Software\Company\Product' Name='LogLevel' Win64='$(var.Win64)'/>
</Property>
Run Code Online (Sandbox Code Playgroud)

这是RegistrySearch的链接

我的代码将注册表值存储到属性中.然后,我试图使用以下代码将其恢复.

<Component Id="RegistryKey">
  <RegistryKey Root='HKLM' Key='Software\Company\Product' Action='createAndRemoveOnUninstall'>
    <RegistryValue Type='int' Name='LogLevel' Value='[LOG_LEVEL]'/>
  </RegistryKey>
</Component>
Run Code Online (Sandbox Code Playgroud)

正如我所说,当看到"int"类型时,Wix会为我添加一个#.因此,Registry表中的值现在是## 1.如果您检查MSDN文档,## 1将被解释为字符串值"#1".因此,我的注册表值使用新类型SZ和新值"#1"重新创建

要解决此问题,我将代码更改为此

<Property Id='LOG_LEVEL' Value='#3'>
  <RegistrySearch Id='LogLevelRegistry' Type='raw' Root='HKLM' Key='Software\Company\Product' Name='LogLevel' Win64='$(var.Win64)'/>
</Property>

<Component Id="RegistryKey">
  <RegistryKey Root='HKLM' Key='Software\Company\Product' Action='createAndRemoveOnUninstall'>
    <RegistryValue Type='string' Name='LogLevel' Value='[LOG_LEVEL]'/>
  </RegistryKey>
</Component>
Run Code Online (Sandbox Code Playgroud)

请注意,虽然我在这里指定了类型"string",但我仍然为我创建了一个DWORD类型的注册表值.这是因为这就是MSI如何解释Registry表中的值.如果注册表值LogLevel不存在(全新安装),我将为其设置默认值#3.如果注册表值LogLevel存在,它将保留现有的LogLevel.

另请注意,此方法有效,因为Wix 3.0不对属性值进行任何处理.它将存储在属性中的值直接放入Registry表中.出于好奇,我也尝试了以下内容.

<RegistryValue Type='string' Name='LogLevel' Value='#1'/>
Run Code Online (Sandbox Code Playgroud)

这次,Wix正确地转义#字符并将## 1放入Registry表中.如果后来Wix也选择在属性值中转义#字符,那么我的解决方案将不起作用.