2010-12-10 121 views
0

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

我发现下面的链接 http://www.mail-archive.com/[email protected]/msg28844.html

我更喜欢使用属性和RegistrySearch方法,而不是自定义操作方法,因为我认为它看起来更简单。

不幸的是,这种方法对我来说效果不好。我的项目有一些DWORD和SZ类型的注册表值。对于所有DWORD类型的注册表值,它在前面附加一个#。我检查了WiX参考手册。这是RegistrySearch的工作原理。

因此,升级后,结果是所有我的DWORD类型注册表被更改为SZ。该值看起来是一样的,只是它在前面附加了一个#。例如,我在类型为DWORD的注册表值“LogLevel”中获得了值2。升级后,我在同一位置使用SZ类型的注册表值“LogLevel”获得值“#2”。

下面是代码片段

<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> 

我不知道是否有任何字符串函数,可以帮助我剪掉从LOG_LEVEL属性“#”我把它放回去了。还是有什么更聪明的方法来保存注册表键进行升级时?我应该采用自定义操作方法吗?

回答

5

我终于得到了RegistrySearch方法的工作。我希望这可能会在未来帮助其他人。

我检查了MSI文档。注册表实际上不包含名为type的列。相反,它以一种奇怪的方式存储该值,以便MSI知道应该创建什么类型的注册表值。在我的情况下,我想创建一个DWORD类型的注册表值。如果我想将数字值1置于注册表值,则该值应该在注册表中存储为#1。这是一个链接到Registry table

那么,为什么Wix RegistryValue有一个强制属性类型?我想这是因为维克斯试图对你很好。如果将该类型标记为int,则可以在值属性中简单地放入“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> 

这里是链接存储在注册表值到属性RegistrySearch

我的代码。然后,我试着用下面的代码把它放回去。

<Component Id="RegistryKey"> 
    <RegistryKey Root='HKLM' Key='Software\Company\Product' Action='createAndRemoveOnUninstall'> 
    <RegistryValue Type='int' Name='LogLevel' Value='[LOG_LEVEL]'/> 
    </RegistryKey> 
</Component> 

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

重建要解决这个问题,我改变了我的代码到althought我指定类型“string”这个

<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> 

注在这里,我仍然有一个为我创建的DWORD类型的注册表值。这是因为这是MSI如何解释Registry表内的值。如果注册表值LogLevel不存在(全新安装),我将为其设置默认值#3。如果注册表值LogLevel存在,它将保留现有的LogLevel。

另请注意,此方法的工作原理是因为Wix 3.0不对属性值进行任何处理。它将存储在属性中的值直接放入注册表表中。 出于好奇,我也尝试了以下。

<RegistryValue Type='string' Name='LogLevel' Value='#1'/> 

这次,Wix正确地转义#字符并将## 1放入注册表中。如果后来Wix选择逃离属性值中的#字符,我的解决方案将无法工作。

0

无论如何,您需要立即为此自定义操作。据称This set of custom actions and extensions有这种行为。您可能会考虑使用它,因为它也声称在企业中经过了良好测试和使用。

希望这会有所帮助。

+0

谢谢,我今天会检查出来 – 2010-12-10 15:22:47