Comment détecter les fonctionnalités actuellement installées lors d’une mise à niveau majeure à l’aide de bundles WiX Burn MBA?

J’utilise les fonctionnalités de l’application Burn / Managed Bootstrapper de WiX 3.7 pour créer un programme d’installation personnalisé basé sur MBA. Pour chacun des paquets de la chaîne de mon paquet, lors de l’exécution d’une mise à jour mineure, je peux facilement détecter quelles fonctionnalités du paquet sont déjà installées pour m’assurer de conserver ces sélections de fonctionnalités pendant la mise à niveau en utilisant ces événements fournis dans la classe de base WiX pour le bootstrapper. : DetectPackageComplete , DetectMsiFeature , DetectRelatedBundle , DetectRelatedMsiPackage , DetectComplete .

Cependant, lors d’une mise à niveau majeure, je ne vois qu’un moyen de déterminer le (s) package (s) installé (s), mais je ne vois pas comment déterminer les fonctionnalités installées, car l’événement DetectMsiFeature ne se déclenche pas. J’ai essayé d’utiliser l’indicateur MigrateFeatures sur la configuration du produit, mais cela ne semble pas fonctionner (ou je ne l’utilise pas correctement).

Quelle est la bonne façon de détecter / migrer les fonctionnalités existantes lors d’une mise à niveau majeure à l’aide d’une application d’amorçage géré personnalisé dans WiX?


Quelques extraits de fichiers:

Remarque: Je peux fournir une solution VS pleinement opérationnelle avec tout le code si cela est utile.

Bundle.wxs:

             

Product.wxs:

                  

CustomBootstrapper.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(ssortingng.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(ssortingng.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(ssortingng.Format("Feature {0} from Package {1} detected in state {2}", e.FeatureId, e.PackageId, e.State)); } private void HandlePackageDetected(object sender, DetectPackageCompleteEventArgs e) { Log(ssortingng.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 */ } } 

Sortie lors de la mise à niveau:

Notez que le package et les deux fonctionnalités ont été installés à la version 1.0.0 et détectés à l’état Absent. Le package associé a été détecté, mais aucun détail de fonctionnalité n’est inclus.

 Kit de mise à niveau associée détectée {5eff0a3c-4b0d-4fd9-875f-05117c07f373) à la version 1.0.0.0 qui est une mise à niveau majeure
 Package NetFx4OWeb détecté dans l'état présent
 Module associé détecté {540AE32D-75C0-4BF3-A72D-ADBE97FSFF3E} (SetupProject1.msi) à la version 1.0.0.0, qui est une mise à niveau principale
 Fonction Feature_one du package SetupProjectl.msi détectée à l'état Absent
 Fonction Feature_Two du package SetupProjecti .msi détectée à l'état Absent
 Package SetupProject1.msi détecté dans un état absent

DetectMsiFeature vous indique l’état des fonctionnalités du nouveau package. ce n’est pas installé, donc évidemment les fonctionnalités ne sont pas. DetectRelatedMsiPackage vous fournit les données dont vous avez besoin pour interroger les états des fonctionnalités de la version installée à l’aide des fonctions MsiEnumFeatures et MsiGetFeatureState / MsiGetFeatureUs de l’API MSI (native).

Je marque la réponse de Bob Arnson comme étant la réponse, car cela me donnait ce dont j’avais besoin pour continuer , mais pour les autres lecteurs de ce message, j’ai pensé donner un peu plus de détails sur la manière de rassembler les états principaux. en utilisant la classe ProductInstallation fournie par WiX (figurant dans l’assembly Microsoft.Deployment.WindowsInstaller.dll, qui se trouve dans le kit de développement WiX), vous évitant ainsi de devoir effectuer vos propres appels directs à l’API MSI native.

Voici un exemple de méthode pouvant être enregistrée pour l’événement DetectRelatedMsiPackage . Notez que vous devez stocker les informations que vous collectez afin de pouvoir définir les états appropriés pendant la phase de planification.

 private void DetectRelatedMsiPackageHandler(object sender, DetectRelatedMsiPackageEventArgs e) { var existingPackageProductCode = e.ProductCode; var actionToBeAppliedToExistingPackage = e.Operation; var existingPackageId = e.PackageId; var existingPackageVersion = e.Version; Log(ssortingng.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(ssortingng.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(ssortingng.Format("Migrating features for MajorUpgrade of Package {0}", existingPackageId)); foreach (var currentInstallFeature in installedPackage.Features) { if (currentInstallFeature.State == InstallState.Local) { Log(ssortingng.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(ssortingng.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 } } } } }