如何在使用WiX Burn MBA捆绑包进行MajorUpgrade期间检测当前安装的功能
本文关键字:检测 MajorUpgrade 功能 安装 包进行 WiX MBA Burn | 更新日期: 2023-09-27 18:21:52
我正在使用WiX 3.7的Burn/Managed Bootstrapper应用程序功能创建一个基于MBA的自定义安装程序。对于我的捆绑包链中的每个包,在执行MinorUpdate时,我可以很容易地检测到哪些包功能已经安装,以确保我在升级期间通过使用引导程序的WiX基类中提供的以下事件来维护这些功能选择:DetectPackageComplete
、DetectMsiFeature
、DetectRelatedBundle
、DetectRelatedMsiPackage
、DetectComplete
。
但是,在MajorUpgrade期间,我只看到了确定安装了哪些软件包的方法,但没有看到如何确定安装了什么功能,因为DetectMsiFeature事件不会触发我尝试在产品配置中使用MigrateFeatures
标志,但似乎不起作用(或者我没有正确使用它)。
在WiX中使用自定义托管引导程序应用程序执行MajorUpgrade时,检测/迁移现有功能的正确方法是什么
一些文件片段:
注意:如果有帮助的话,我可以提供一个完整的VS解决方案,其中包含所有代码。
捆绑包.wxs:<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="Bootstrapper1" Version="1.1.0.0" Manufacturer="Knights Who Say Ni" UpgradeCode="e6fbf160-d1d9-4b38-b293-94d60eae876f" Compressed="yes">
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" >
<Payload SourceFile="$(var.ManagedBootstrapperApplication.TargetPath)" />
<!-- other files here -->
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx40Web" />
<MsiPackage SourceFile="$(var.SetupProject1.TargetPath)" EnableFeatureSelection="yes" Vital="yes" Compressed="yes" />
</Chain>
</Bundle>
</Wix>
产品.wxs:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SetupProject1" Language="1033" Codepage="1252"
Version="1.1.0.0" Manufacturer="Knights Who Say Ni"
UpgradeCode="5fcd463a-3287-4fdf-bf00-d5d74baeccda">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade AllowSameVersionUpgrades="no" AllowDowngrades="no" MigrateFeatures="yes" DowngradeErrorMessage="Bring me a shrubbery!" />
<MediaTemplate EmbedCab="yes" />
<Feature Id="feature_one" Title="Primary Feature" Level="1">
<Component Id="CMP_emptyFile1" Guid="{1740AFA6-A98F-482A-B319-A153AA1BEF10}" Directory="INSTALLFOLDER">
<File Id="file_emptyFile1" Checksum="yes" KeyPath="yes" Source="TextFile1.txt" />
</Component>
</Feature>
<Feature Id="feature_Two" Title="Optional Feature" Level="2">
<Component Id="CMP_emptyFile2" Guid="{F0831C98-AF35-4F5E-BE9A-2F5E3ECF893C}" Directory="INSTALLFOLDER">
<File Id="file_emptyFile2" Checksum="yes" KeyPath="yes" Source="TextFile2.txt" />
</Component>
</Feature>
</Product>
</Wix>
自定义引导程序.cs
public class CustomBootstrapperApplication : BootstrapperApplication {
protected override void Run() {
DetectPackageComplete += HandlePackageDetected;
DetectMsiFeature += HandleFeatureDetected;
DetectRelatedBundle += HandleExistingBundleDetected;
DetectRelatedMsiPackage += HandleExistingPackageDetected;
DetectComplete += HandleDetectComplete;
this.Engine.Detect();
//blocks here until DetectComplete fires...
}
private void HandleExistingPackageDetected(object sender, DetectRelatedMsiPackageEventArgs e) {
Log(string.Format("Detected Related Package {2} ({1}) at version {3} which is a {0}",
e.Operation, e.PackageId, e.ProductCode, e.Version));
}
private void HandleExistingBundleDetected(object sender, DetectRelatedBundleEventArgs e) {
Log(string.Format("Detected Related {2} Bundle {0} at version {1} which is a {3}",
e.ProductCode, e.Version, e.RelationType, e.Operation));
}
private void HandleFeatureDetected(object sender, DetectMsiFeatureEventArgs e) {
Log(string.Format("Feature {0} from Package {1} detected in state {2}",
e.FeatureId, e.PackageId, e.State));
}
private void HandlePackageDetected(object sender, DetectPackageCompleteEventArgs e) {
Log(string.Format("Package {0} Detected in State {1}",
e.PackageId, e.State));
}
private void HandleDetectComplete(object sender, DetectCompleteEventArgs e)
{ /* release the main thread to continue with work */ }
}
升级时的输出:
请注意,该软件包和两个功能都安装在v1.0.0版本,并在Absent状态下检测到。检测到相关程序包,但不包括任何功能详细信息。
检测到1.0.0.0版本的相关升级捆绑包{5ef0a3c-4b0d-4fd9-875f-05117c07f373),它是一个主要升级检测到包NetFx4OWeb处于存在状态检测到1.0.0.0版本的相关程序包{540AE32D-75C0-4BF3-A72D-ADBE97FSFF3E}(SetupProject1.msi),该程序包是MajorUpgrade在状态Absent中检测到程序包SetupProject.msi中的功能Feature_one功能Feature_Two from Package SetupProjection.msi detected in state Absent在"不存在"状态下检测到程序包SetupProject1.msi
我将Bob Arnson的回应标记为答案,因为它为我提供了推动这一进程所需的东西,但对于其他看到这篇文章的人来说,我想我应该提供更多关于如何使用WiX提供的ProductInstallation
类(可在WiX SDK中的Microsoft.Deployment.WindowsInstaller.dll程序集中找到)收集功能状态的细节,从而消除了对本机MSI API进行直接调用的需要。
下面是一个可以注册到DetectRelatedMsiPackage
事件的方法示例。请注意,您需要存储收集到的信息,以便在计划阶段设置适当的状态。
private void DetectRelatedMsiPackageHandler(object sender, DetectRelatedMsiPackageEventArgs e)
{
var existingPackageProductCode = e.ProductCode;
var actionToBeAppliedToExistingPackage = e.Operation;
var existingPackageId = e.PackageId;
var existingPackageVersion = e.Version;
Log(string.Format("Detected existing related package {0} (product: {1}) at version {2}, which will be {3}",
existingPackageId, existingPackageProductCode, existingPackageVersion,
actionToBeAppliedToExistingPackage));
if (actionToBeAppliedToExistingPackage == RelatedOperation.MajorUpgrade)
{
//requires reference to WiX Toolset'SDK'Microsoft.Deployment.WindowsInstaller.dll
var installedPackage = new Microsoft.Deployment.WindowsInstaller.ProductInstallation(existingPackageProductCode);
if (!installedPackage.IsInstalled) {
Log(string.Format("Migrating Package {0}, which is not installed, so marking it and it's features as Absent", existingPackageId));
//TODO: add logic to store state so that during Plan phase can set package with package with product code = existingPackageProductCode to PackageState.Absent
} else {
Log(string.Format("Migrating features for MajorUpgrade of Package {0}", existingPackageId));
foreach (var currentInstallFeature in installedPackage.Features) {
if (currentInstallFeature.State == InstallState.Local) {
Log(string.Format("Migrating feature {1} of Package {0} - marking as Present", existingPackageId, currentInstallFeature.FeatureName));
//TODO: add logic to store state so that during Plan phase can set package and feature states based on this info
} else {
Log(string.Format("Migrating feature {1} of Package {0} - marking as Absent", existingPackageId, currentInstallFeature.FeatureName));
//TODO: add logic to store state so that during Plan phase can set package and feature states based on this info
}
}
}
}
}
DetectMsiFeature
告诉您新包的功能状态;它没有安装,所以功能也没有。DetectRelatedMsiPackage
为您提供使用(本机)MSI API函数MsiEnumFeatures
和MsiGetFeatureState
/MsiGetFeatureUsage
查询已安装版本的功能状态所需的数据。