2

鉴于:

  1. Wix 3.0 用于创建 MSI。
  2. 该产品由多个功能组成。
  3. 每个功能都有几个子功能。这是一个标准的 MSI 功能树。
  4. 每个功能或子功能都依赖于多个外部组件。例如 .NET 4、ASP.NET 等
  5. 使用 Wix 3.0 SDK 以 C# 编写的自定义操作会处理这些依赖关系,并评估给定功能集是否存在组件。
  6. 在安装时,如果缺少给定功能选择的依赖组件,安装将失败。

实现: 无需在给定机器上安装 MSI 即可执行先决条件检查,这已在 MSI 中作为安装期间的自定义操作完成。

失败的尝试:

1) 自定义操作具有这样的功能签名

[CustomAction]
public static ActionResult ProcessFeaturePrerequisite(Session session);

为了获得会话对象,我使用了 Wix 3.0 SDK 中的以下 API

Session session = Installer.OpenPackage("Pathto\\Product.msi", true); // true doesn’t install it. Also tried with false, but didn’t work.

当我用上面的会话调用上面的方法时,事情失败了。

session.Features["SomeFeature"].CurrentState;

这会引发异常。

System.ArgumentException was unhandled by user code
  Message=Feature ID not registered. SomeFeature
  Source=Microsoft.Deployment.WindowsInstaller
  StackTrace:
       at Microsoft.Deployment.WindowsInstaller.FeatureInfo.get_CurrentState()

同样在确定先决条件状态的关键 API 下,总是返回 false。

session.EvaluateCondition(prereq);

2) 我知道一种命令行方式来指定上述 MSI 的功能并安装它。它是这样的

msiexec /i "Product.msi" ADDLOCAL=ALL REMOVE="Foo,Bar " 

我在 SDK 中找不到任何 API,它允许我传递额外的参数,这些参数在不开始安装的情况下返回会话对象。我的猜测是传递这样的参数将使 session.Features 更有效。

问题: 那么我如何实现上述目标?有没有

  1. Wix SDK 中的任何 API 允许我在不调用安装的情况下调用自定义操作?
  2. 有什么方法可以在不安装的情况下从命令行为给定的 MSI 调用自定义操作?
  3. 有什么方法可以让 Wix 将 MSI 更改为接受包含仅评估操作的自定义操作名称的命令字符串?
  4. 有更好的方法来做同样的事情吗?
4

1 回答 1

2

我想您正在尝试使用错误的工具来解决问题。据我了解,您想从某个工具中检查安装先决条件,而不是从安装中检查。只要该功能作为 MSI 包中的自定义操作实现,您就希望利用该功能以避免重复代码。

在您的情况下,我会选择不同的方式:

  1. 将实际检查先决条件的功能提取到单独的程序集中,例如checkprereq.dll
  2. 重构您的自定义操作以引用checkprereq.dll. 请注意,您必须添加checkprereq.dll到您的Binary表以及customaction.dll. 您应该在此处划分责任:自定义操作部分与 MSI 内容一起使用-在您的情况下,它根据用户选择的功能组合定义要检查的先决条件-以及功能部分-实际先决条件验证,由checkprereq.dll
  3. checkprereq.dll当您需要检查不触发安装过程的先决条件时单独使用

您在此处概述的尝试证明了一个重要的错误假设:session安装时的对象与您仅出于只读目的打开 MSI 数据库获得的安装对象相同。这不是真的!session实际上,我怀疑在安装事务之外引用该对象是否有意义。顾名思义,它是一个安装会话,即在进程中可用 - 不是静态的。

当 MSI 包只是一个文件而不是正在运行的安装时,它应该被视为一个数据库。因此,当您打开它进行阅读而不是安装时,只能查询和使用MSI包中的静态信息。例如,我的意思是您可以查询该Feature表,但不要期望它包含仅在安装时有意义的信息,例如用户是否选择了要安装的功能。

希望这是有道理的,并向您展示正确的方向。

于 2012-08-03T13:28:03.797 回答