WiX RemoveRegistryKey 元素的行为不像宣传的那样

Posted

技术标签:

【中文标题】WiX RemoveRegistryKey 元素的行为不像宣传的那样【英文标题】:WiX RemoveRegistryKey element not behaving as advertised 【发布时间】:2017-07-04 13:10:23 【问题描述】:

卸载时似乎无法删除注册表项。请注意,这不是this 问题的重复,因为我认为我没有同样的问题。或者,如果我这样做了,我想澄清一下为什么。当我在新的 VM 上安装时会出现此问题,因此我不是在同一个 GUID 之上安装的。

我正在做的是将来自用户(来自 UI)的值放入一些属性中,然后通过 CustomAction 将这些值导入到一些 C# 代码中,然后我在其中加密这些值并将它们放入一个注册表项。

我不使用 WiX 将值放入注册表项,而是通过 C# 代码进行。原因是我似乎无法将属性导入 C# 自定义操作,然后将相同代码中的值导出回 WiX(我可以单独执行每个操作都没有问题)。但这是一个不同的问题......

无论如何,我得到这些值,加密它们,并将它们放入注册表项中就好了。卸载时我似乎无法删除注册表项。奇怪的是,它确实删除了键中除一个之外的每个值,但它不会删除整个键。

这是应该删除密钥(但不会)的 XML:

        <Component Id="Component_CleanRegistryOnUninstall"
               Directory="TARGETDIR"
               Guid="86D04E28-2EF8-4A6C-BB9B-577EA1597BB5" 
               KeyPath="yes">
        <RemoveRegistryKey Id="CleanupRegistry"
                           Root="HKLM"
                           Key="Software\...\...\InstallCfg"
                           Action="removeOnUninstall"/>
        </Component>

这是创建 C# 自定义操作的 XML:

    <Fragment>      
  <Property Id="VAL1" Hidden="yes"/>
  <Property Id="VAL2" Hidden="yes"/>
  <Property Id="VAL3" Hidden="yes"/>
  <Property Id="VAL4" Hidden="yes"/>

  <SetProperty Id="CustomAction_PassProperty"
               Value="VAL1=[VAL1];VAL2=[VAL2];VAL3=[VAL3];VAL4=[VAL4]"
               Sequence="execute"
               Before="CustomAction_PassProperty"/>

  <Binary Id="Binary_PassProps"
          SourceFile="$(var.CreateRegistryKey.TargetDir)CreateRegistryKey.CA.dll"/>

  <!-- Note that 'Impersonate="no"' elevates the privilege of the C# code, needed to create keys -->
  <CustomAction Id="CustomAction_PassProperty"
                BinaryKey="Binary_PassProps"
                DllEntry="CreateKeys"
                Execute="deferred"
                Impersonate="no"
                Return="check" 
                HideTarget="yes"/>

  <InstallExecuteSequence>
      <Custom Action="CustomAction_PassProperty"
              After="InstallInitialize"/>
  </InstallExecuteSequence>
</Fragment>

这是 C# 本身:

        [CustomAction]
    public static ActionResult CreateKeys(Session session)
    
        // encrypt and set set the registry keys
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\...\\...\\InstallCfg", "Val1", Encrypt(session.CustomActionData["VAL1"]));
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\...\\...\\InstallCfg", "Val2", Encrypt(session.CustomActionData["VAL2"]));
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\...\\...\\InstallCfg", "Val3", Encrypt(session.CustomActionData["VAL3"]));
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\...\\...\\InstallCfg", "Val4", Encrypt(session.CustomActionData["VAL4"]));

        // also, set the "SettingsProcessed" key to false
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\...\\...\\InstallCfg", "SettingsProcessed", "false");

        return ActionResult.Success;
    

设置的最终值——刚刚作为“假”而不是加密值传入的值——是一个标志,可能是问题的关键。

这是一种奇怪的行为:当我卸载时,密钥并没有被删除,但它确实删除了所有值除了一个没有被删除的值传递给 C# 函数,标志。它不会被删除。但是,即使我创建了一个属性,也要为该属性赋予值“false”,然后将其传递给 C#,如下所示:

Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\...\\...\\InstallCfg", "SettingsProcessed", session.CustomActionData["SETTINGSPROCESSED"]);

同样的事情发生了:除它之外的所有其他值都被删除。我承认这可能是组件问题,答案可能在this 答案中,但我无法弄清楚。

总结一下:注册表项已创建,但&lt;RemoveRegistryKey&gt; 不会在卸载时将其删除。

编辑::

Bob 从来没有让他的&lt;RemoveRegistryKey&gt; 元素起作用。他退出 IT 并搬到奥马哈,在那里经营一家黎巴嫩/荷兰比萨店并练习班卓琴。

不,真的,我从来没有让它工作。我最终创建了 另一个 删除密钥的自定义操作。这太令人沮丧了,让我想搬到奥马哈。

【问题讨论】:

【参考方案1】:

您需要设置条件在卸载期间不运行CustomAction_PassProperty。 像这样:

  <InstallExecuteSequence>
      <Custom Action="CustomAction_PassProperty"
              After="InstallInitialize>NOT REMOVE="ALL"</Custom>
  </InstallExecuteSequence>

它“删除所有值”除了硬编码的值可能是因为您在卸载期间重写了 VAL1, VAL2... 的值,此时这些属性可能为空(它们仅在安装期间在 ui 中设置顺序对吗?)。

【讨论】:

感谢您的回复!是的,属性仅在 UI 序列期间设置,硬编码标志除外。在卸载期间它们会被删除是有道理的(硬编码标志除外)。当我提出您建议的条件时,我确实得到了不同的行为 - 现在,当我卸载时,它不会删除这些值。 VAL1,..., VALX 以及标志仍然存在。然而,这不是我想做的。我想完全删除注册表项。 This 对话澄清了很多关于条件的问题——如何让自定义操作在您需要时运行。我需要做的是:让我的自定义操作仅在安装和维修期间运行。 另外,在卸载过程中,我需要删除自定义操作创建的注册表项。这就是我卡住的地方。 您是否在 中引用了Component_CleanRegistryOnUninstall 组件?此外,我建议记录卸载并查看与组件相关的情况。做yourmsi.msi /x /l*v log.txt 是的,我确实引用了该组件。我想知道如何记录卸载——它必须是 /x 标志!我会这样做的!

以上是关于WiX RemoveRegistryKey 元素的行为不像宣传的那样的主要内容,如果未能解决你的问题,请参考以下文章

WiX:错误 RegistryKey 元素包含意外属性“ForceDeleteOnUninstall”

使用条件元素禁用 WIX 中的复选框

wix - 错误 CNDL0004:从命令行运行时文件元素包含意外的属性“src”

为啥 FileSearch 元素的 MinVersion 属性在我的 WiX 安装程序中不起作用?

在 wix 3.8 中将 wxs 文件添加到 product.wxs 文件

如何将文件添加到 WiX Burn 中的 Container 元素?