Wix 工具更新使用旧的自定义操作 [英] Wix Tools update uses old custom actions

查看:34
本文介绍了Wix 工具更新使用旧的自定义操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在使用 WIX 安装工具时发现了一些奇怪的行为.我们已经部署了一些主要版本(2.2.0 - 到 2.2.4).对于 2.2.5,我们在自定义操作中做了一些小改动(在我们使用 XCOPY 之前,现在我们使用 RoboCopy 因为它有一个移动"命令而不仅仅是一个副本).

we've discovered some strange behavior using WIX Setup Tools. We have deployed some major versions (2.2.0 - to 2.2.4). For 2.2.5 we changed a small things in custom actions (before we used XCOPY, now we use RoboCopy because this has a "MOVE" command and not only a copy).

但是当我们现在从 2.2.4 更新到 2.2.5 时,安装程​​序仍然使用旧的 Copy 命令而不是新的 MOVE 命令,但这不可能是因为 2.2.5 没有任何 Copy 命令.如果我部署 2.2.6(与 2.2.5 相同)并从 2.2.5 更新,它将使用新的更新过程...更新似乎使用了旧的 MSI.

But when we now update from 2.2.4 to 2.2.5 the setup still uses the old Copy command instead of the new MOVE Command but this can't be because 2.2.5 does not have any Copy command. If I deploy a 2.2.6 (identical with 2.2.5) and update from 2.2.5 it uses the new update process... It looks like the update uses the old MSI.

在 SO 上找到这个

有什么办法可以防止这种行为?这完全中断了更新过程,因为在更新时没有正确复制现有的配置文件.

Is there any way to prevent this behavior? This completely breaks update process as existing config files are not copied correctly on update.

我们不能通过 GUID 强制客户清理注册表或删除任何 MSI 文件表单缓存...

We can't force the customer to clean registry or remove any MSI files form cache by GUID...

任何帮助表示赞赏.提前致谢

Any help appreciated. Thanks in advance

更新:Product.wxs 中的新自定义操作

UPDATE: New Custom Action in Product.wxs

<Property Id="C_TEMP" Value="C:\Temp" />
      <Property Id="ROBOCOPY_EXE">robocopy.exe</Property>
      <CustomAction Id="CopyToTemp" Property="ROBOCOPY_EXE" Return="ignore" ExeCommand='"[INSTALLDIR]\Configuration" "[C_TEMP]\ServerSettings" ServerSettings.json' />
      <CustomAction Id="CopyFromTemp" Property="ROBOCOPY_EXE" Return="ignore" ExeCommand='"[C_TEMP]\ServerSettings" "[INSTALLDIR]\Configuration" ServerSettings.json /MOVE /IS' />

旧的自定义操作

<Property Id="C_TEMP" Value="C:\Temp" />
  <Property Id="XCOPY_EXE">xcopy.exe</Property>
  <CustomAction Id="CopyToTemp" Property="XCOPY_EXE" Return="ignore" ExeCommand='"[INSTALLDIR]\Configuration\ServerSettings.json" "[C_TEMP]\ServerSettings.json.bak*" /YIR' />
  <CustomAction Id="CopyFromTemp" Property="XCOPY_EXE" Return="ignore" ExeCommand='"[C_TEMP]\ServerSettings.json.bak" "[INSTALLDIR]\Configuration\ServerSettings.json*" /YIR' />

之后代码至今没有改变

<InstallExecuteSequence>
  <Custom Action="CopyToTemp" Before="InstallInitialize">Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)</Custom>
  <Custom Action="CopyFromTemp" Before="SetVersionsInRegistry">NOT Installed OR Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)</Custom>

.....
</InstallExecuteSequence>

推荐答案

测试条件

条件 1:

已安装且(NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

这种相当奇怪的条件组合将导致有问题的自定义操作在全新安装或手动卸载期间无法运行.似乎此自定义操作将在以下期间运行:主要升级(这是一种特殊类型的卸载)、修改和修复.我想这可以完成备份设置文件的工作.不过……

This rather odd constellation of conditioning will cause the custom action in question to not run during a fresh install, nor a manual uninstall. It seems this custom action will run during: major upgrade (which is a special type of uninstall), modify and repair. I suppose this would do the job of backing up the settings file. However...

在重大升级期间,这确实看起来像是在运行旧的自定义操作,因为正在运行的是处于主要升级模式(这是一种特殊类型的卸载)的旧包 - 因此具有旧包的自定义操作(运行的是您之前安装的旧缓存数据库 - 作为主要升级的一部分,它会自行卸载).这些自定义操作从未在包的初始安装期间运行.但是您要从 temp 复制的其他自定义操作会.这可能不是正确的行为.

During a major upgrade this would indeed look like the old custom action is being run, because what is running is your old package in major upgrade mode (which is a special type of uninstall) - hence featuring the old package's custom actions (what is running is the old, cached database from your previous install - it uninstalls itself as part of the major upgrade). These custom actions never ran during the package's initial install. But your other custom action to copy from temp will. That is probably not correct behavior.

总结:

  • 运行:主要升级(通过卸载的旧 MSI 运行,但不在新 MSI 中运行)、修改、修复
  • 不运行:第一次安装,卸载.
  • Runs: major upgrade (run via the old MSI that uninstalls, but not in the new MSI), modify, repair
  • Does not run: first time install, uninstall.

条件 2:

NOT Installed OR Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

第二个条件也有点奇怪,似乎只能在全新安装和重大升级时运行.您可能只需要在主要升级期间运行它,但您不应该也在修复和修改期间运行吗?(这些模式在某些情况下也可以覆盖设置文件,例如当 REINSTALLMODE 设置为amus"以强制覆盖文件时).

The second condition, which is also a little exotic, seems to run on a fresh install and a major upgrade only. You probably only need it to run during major upgrade, but shouldn't you also run during repair and modify? (these modes can also overwrite the settings file in certain cases, such as when REINSTALLMODE is set to "amus" to force overwrite files).

总结:

  • 运行:首次安装,主要升级
  • 不运行:卸载、修改、修复
  • Runs: first time install, major upgrade
  • Does not run: uninstall, modify, repair

我并没有完全掌握您的整个场景,但是您可以找到几个资源链接以在此处查找常见条件:是否可以仅在修复模式下运行自定义操作.我假设您想在主要升级、修复和修改时备份设置文件以避免它被覆盖.看起来应该对条件进行一些修改才能实现这一点?

I don't really have a full grasp of your whole scenario, but you can find a couple of links to resources to find common conditions here: Is it possible to run a custom action only in repair mode. I assume you want to back up the settings file on major upgrade, repair and modify to avoid it being overwritten. It looks like the conditions should be modified somewhat to achieve this?

我建议完全避免自定义操作,以下是实现此目的的建议方法.

设置文件的管理和设置一直是部署的难题.几天前,我写了一个关于处理用户设置文件的不同方法的简短摘要:在当前用户配置文件上创建文件夹和文件,从管理员配置文件(这是部署设置文件的不同方法的一点参考- 推荐,如果不清楚,请告诉我).

The management and setup of settings files has always been a difficult issue for deployment. I wrote up a short summary of different ways to deal with user settings files a few days ago: Create folder and file on Current user profile, from Admin Profile (it is a little reference of different ways to deploy settings files - recommended, and please let me know if it is unclear).

从上面的链接答案中可以看出,使用您的应用程序将设置文件从由您的设置安装到 INSTALLDIR 中的只读位置的模板副本中初始化设置文件通常是一个好主意.然后,您将保持模板不变,但在启动时,您的应用程序会将您的模板设置文件复制到每个用户的用户配置文件中,或者它只是在安装过程永远不会触及的 INSTALLDIR 中创建一个副本(您需要应用 ACL 权限才能做到这一点)所有用户都可以写入的设置文件 - 不是很好的设计,但它确实有效).这种基于模板的方法将设置文件与部署注意事项分离开来.从现在开始,它将永远不会被重置、卸载或干预,因为它从未被安装程序安装.事实上,您必须专门实施其清理或卸载(例如通过 RemoveFolder/RemoveFile 构造),否则卸载时它会保留在磁盘上 - 这也可能是一个问题.

As can be seen in the linked answer above, it is often a good idea to use your application to initialize settings files from template copies that are installed by your setup to a read-only location in INSTALLDIR. You would then leave the template unchanged, but on launch your application copies your template settings file to each user's user profile, or it just creates a copy in INSTALLDIR that the install process never will touch (you would need to apply ACL permissioning to make this settings file writeable by all users - not great design, but it does work). This template-based approach de-couples the settings file from deployment considerations. It will never be reset, uninstalled or meddled with from now on, since it was never installed by the setup. In fact you have to implement its cleanup or uninstall specifically (for example via a RemoveFolder / RemoveFile construct), or it will remain on disk on uninstall - which can also be a problem.

避免使用 Windows Installer 处理自定义操作的复杂体系结构始终是一个优势.对于您调用的各种二进制文件,有复杂模拟复杂条件复杂排序以及运行时依赖.您是使用 DTF 还是直接调用 C# 程序集?使用托管自定义操作存在一些问题(加载了错误的 CLR 版本、根本没有安装 .NET(锁定?)、对 GAC 中文件的依赖等......我没有完整的概述 - 我留下来由于这些原因,远离所有用于 MSI 部署的托管代码).

It is always an advantage to avoid Windows Installer's complex architecture for dealing with custom actions. There is complex impersonation, complex conditioning, complex sequencing and also runtime dependencies for various binaries you call. Are you using DTF or just a straight C# assembly to call? There are some problems with the use of managed custom actions (wrong CLR version loaded, no .NET installed at all (locked?), dependencies on files in the GAC, etc... I don't have a full overview - I stay away from all managed code for MSI deployment for these reasons).

将模板设置文件复制到安装程序无法访问的新文件时,您无需处理 MSI 的奇思妙想 - 或任何托管自定义操作及其运行时要求.

When copying template settings files to a new file that is untouchable by your installer you will not have to deal with MSI's whims and quirks - or any managed custom actions and their runtime requirements.

更新:我删除了之前添加的传递方法,因为进一步测试表明它仅在某些情况下有效.我将使用小升级而不是大升级再次检查它.然后,您可以使用次要升级补丁来迁移所有旧版本以将设置文件设置为永久,以便永远不会再次卸载它,然后您将应用您的主要升级.这应该可以包装在 Burn bootstrapper 中.

UPDATE: I remove the transitive approach I added earlier after further testing revealed it will only work in certain cases. I will check it again using minor upgrade instead of major upgrade. You could then use a minor upgrade patch to migrate all old version to set the settings file permanent so it is never uninstalled again, and then you would apply your major upgrade. This should be possible to wrap in a Burn bootstrapper.

更新:假设(并验证)小升级可以将任何组件切换为永久组件,并​​且不需要为组件使用任何传递设置(我没有检查小更新是否可以如果之前将组件设置为永久,则将其切换为非永久).事实上,如果在安装过程中附加到组件的任何条件评估为 false,启用传递实际上可以卸载该组件 - 我没有验证这一点,但从逻辑上讲这是可能的.首先想到的是这是否可以卸载设置为永久的组件.它不应该,但我以前在 MSI 上见过这种奇怪的情况.例如,我可以想象这是永久部署到 System32 的组件集所必需的.结论:如果您只需要保留设置文件,只需使用小升级将其设置为永久,然后您就可以再次使用大升级.不要将组件设置为可传递的.

UPDATE: as assumed (and verified) a minor upgrade can switch any component to permanent and there is no need to use any transitive settings for the component (I did not check if a minor update can switch a component to be non-permanent if it was set permanent before). In fact enabling transitive could actually uninstall the component if any condition attached to the component evaluates to false during the installation - I did not verify this, but it makes logical sense that it could be possible. The first thing that comes to mind is whether this could uninstall a component set to permanent. It shouldn't, but I have seen such weirdness before with MSI. I can picture this necessary for a component set permanent deployed to System32 for example. In conclusion: if all you need is to preserve a settings file, just use a minor upgrade to set it permanent and then you can use major upgrades again. Don't set the component transitive.

顺便提一下:您的设置文件实际上并没有被您当前的升级方案覆盖.它在主要升级期间被卸载并重新安装,因为它的组件最初没有设置为 Permanent = "yes"NeverOverwrite="yes".这似乎已将其恢复为默认值,但从未被覆盖.相反,它被卸载并重新安装以消除更改.MSI 不会覆盖更改过的、非版本化的文件,但它会很乐意卸载并重新安装它们,除非它们被标记为永久.在我看来这是一种技术反模式 - 许多团队一直面临这个问题.因此,我建议查看此处描述的一些数据文件部署选项:从管理员配置文件在当前用户配置文件中创建文件夹和文件(与上面相同的链接).

Just to mention it: your settings file is in fact not being overwritten by your current upgrade scheme by the way. It is being uninstalled and reinstalled during the major upgrade because its component was not originally set to Permanent = "yes" and NeverOverwrite="yes". This appears to have reverted it to the default values, but it was never overwritten. Rather it was uninstalled and reinstalled wiping out changes. MSI will not overwrite changed, non-versioned files, but it will happily uninstall and reinstall them unless they are marked permanent. It is a technology anti-pattern in my opinion - a lot of teams face this problem all the time. Hence my suggestion to review some data file deployment options as described here: Create folder and file on Current user profile, from Admin Profile (same link as above).

我希望其中有一些帮助,请告诉我们您在测试过程中的发现.

I hope some of this helps, and please let us know what you find during testing.

旧答案:

Brian 提到了真正的建议,但可能还有一些问题需要澄清.一旦我有一些答案,我会将其演变为一个尝试性的答案.

Brian's mentioned the real advice, but maybe some questions for clarification. I will evolve this into an attempted answer once I have some answers.

  • 这些自定义操作是如何运行的?它们是 EXE 命令还是您正在运行启动器 EXE 然后调用它们?如果您使用这样的启动器 EXE,它是本机 (C++) 还是 .NET?(C#/VB.NET).如果是 .NET,那通常是个坏消息.
  • 我们能问一下你用这些复制命令做什么吗?这可以在应用程序本身中更可靠地完成吗?这可能是我们给人们的最常见的建议,如果遵循这些建议,实际上可以大大简化部署并使其更可靠.您可以更好地控制应用程序中发生的事情,在可预测的安全上下文中运行,并且无需处理任何条件或顺序.最后:您可以重新启动应用程序并再次执行,设置是一次性的".
  • 我暂且不谈...

这篇关于Wix 工具更新使用旧的自定义操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆