Как определить установленные функции во время MajorUpgrade с помощью пакетов Wix Burn MBA?

я использую функции приложения Wix 3.7 Burn / Managed Bootstrapper для создания пользовательского установщика на основе MBA. Для каждого из пакетов в цепочке моего пакета при выполнении MinorUpdate я могу легко определить, какие из функций пакета уже установлены, чтобы гарантировать, что я поддерживаю эти параметры во время обновления, используя эти события, предоставленные в базовом классе WiX для загрузчика:DetectPackageComplete, DetectMsiFeature, DetectRelatedBundle, DetectRelatedMsiPackage, DetectComplete.

однако, во время MajorUpgrade я вижу только способ определить, какие пакеты установлены, но не вижу, как определить, какие функции установлены, поскольку событие DetectMsiFeature не срабатывает. я попытался с помощью MigrateFeatures флаг в конфигурации продукта, но это, похоже, не работает (или я не использую его правильно).

как правильно обнаружить / перенести существующие функции при выполнении MajorUpgrade с помощью настраиваемого управляемого загрузчика Применение в WiX?


некоторые фрагменты файла:

Примечание: я могу предоставить полностью рабочее решение 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>

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(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 и обнаружен в состоянии отсутствует. Соответствующий пакет был обнаружено, но не включены сведения о функциях.

Detected Related Upgrade Bundle {5eff0a3c-4b0d-4fd9-875f-05117c07f373) at version 1.0.0.0 which is a MajorUpgrade
Package NetFx4OWeb Detected in State Present
Detected Related Package {540AE32D-75C0-4BF3-A72D-ADBE97FSFF3E} (SetupProject1.msi) at version 1.0.0.0 which is a MajorUpgrade
Feature feature_one from Package SetupProjectl.msi detected in state Absent
Feature feature_Two from Package SetupProjecti .msi detected in state Absent
Package SetupProject1.msi Detected in State Absent

2 ответов


DetectMsiFeature сообщает вам состояние функций для нового пакета; он не установлен, поэтому, очевидно, что функции не установлены. DetectRelatedMsiPackage предоставляет данные, необходимые для запроса состояний компонентов установленной версии с помощью (собственных) функций API MSI MsiEnumFeatures и MsiGetFeatureState/MsiGetFeatureUsage.


я помечаю Боб Arnson это!--5--> в качестве ответа, так как он дал мне то, что мне нужно, чтобы подтолкнуть это, но для других, кто сталкивается с этим сообщением, Я думал, что дам немного больше информации о том, как вы можете собрать состояния функций с помощью Wix-provided ProductInstallation класс (найден в Microsoft.Развертывание.WindowsInstaller.dll сборка, которая находится в Wix SDK), тем самым устраняя необходимость совершать собственные прямые вызовы собственного 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
                }
            }
        }
    }
}