如何使用自定义引导程序执行Wix升级

时间:2018-05-15 10:28:14

标签: c# wix upgrade bootstrapper

我想在我们的WiX自定义BA安装程序的第二版中启用升级。在我的Product.wxs中,产品ID设置为*,版本设置为2.0.0,升级代码保持与第一个版本相同。为了检测升级,我在Boostrapper中使用了DetectRelatedBundle事件处理程序。

MSI中的MajorUpgrade标记如下所示:

<MajorUpgrade AllowDowngrades="no" DowngradeErrorMessage="A newer version of [ProductName] is already installed." AllowSameVersionUpgrades="no" Schedule="afterInstallInitialize" />

在我的安装程序用户界面中,我有一个安装按钮。在升级方案期间单击此按钮时,我调用PlanAction并传递LaunchAction.Install。但是一旦安装开始,它会显示BA的另一个实例,我相信这是我目前的BA调用的旧包,用于卸载旧版本。为了隐藏新的BA实例并只显示安装进度,我在我的Bootstrapper中进行了这些更改:

Bootstrapper.cs:

protected override void Run()
{
    BootstrapperDispatcher = Dispatcher.CurrentDispatcher;

    try
    {
        _model = new BootstrapperApplicationModel(this);

        var uninstall = new UpgradeUninstall(_model);
        if (uninstall.IsUpgradeUninstallation())
        {
            uninstall.PerformSequence();
        }
        else
        {
            //show install or uninstall main UI

            this.WireUpEventHandlers();
            _model.BootstrapperApplication.Engine.Detect();
            Dispatcher.Run();
        }
    }
}

UpgradeUninstall.cs:

public class UpgradeUninstall
{
    private BootstrapperApplicationModel _bootStrapperModel;

    public UpgradeUninstall(BootstrapperApplicationModel model)
    {
        _bootStrapperModel = model;
    }       

    public void Perform()
    {
        this.WireUpEventHandlers();
        _bootStrapperModel.BootstrapperApplication.Engine.Detect();
    }

    public bool IsUpgradeUninstallation()
    {
        var action = _bootStrapperModel.BootstrapperApplication.Command.Action;
        var display = _bootStrapperModel.BootstrapperApplication.Command.Display;

        return action == LaunchAction.Uninstall && (display == Display.None || display == Display.Embedded);
    }

    private void WireUpEventHandlers()
    {
        _bootStrapperModel.BootstrapperApplication.DetectComplete += OnDetectComplete;
        _bootStrapperModel.BootstrapperApplication.PlanComplete += OnPlanComplete;
        _bootStrapperModel.BootstrapperApplication.ApplyComplete += OnApplyComplete;
    }

    private void OnDetectComplete(object sender, DetectCompleteEventArgs e)
    {
        this._bootStrapperModel.PlanAction(LaunchAction.Uninstall);
    }

    private void OnPlanComplete(object sender, PlanCompleteEventArgs e)
    {
        this._bootStrapperModel.ApplyAction();
    }

    private void OnApplyComplete(object sender, ApplyCompleteEventArgs e)
    {
        BootstrapperDispatcher.InvokeShutdown();
    }
}

问题1)如何让我的主BA实例(安装人员)知道卸载旧包已经完成?现在发生的是它能够成功卸载旧包,但是没有安装新版本。

问题2)我对WiX升级的理解是否正确? :)

1 个答案:

答案 0 :(得分:0)

正在发生的事情是您的旧BA通过卸载开关以静默方式被调用。我看不到您的代码确实可以处理一些命令行卸载,尽管我看不到您在哪里调用Engine.Plan(LaunchAction.Uninstall)。

Q1)我不认为您需要做任何特别的事情来让您的原始BA知道您已经完成。您只需要以正常方式退出安装即可。

Q2)是的,我认为您快到了。我建议您从git下载WIX源代码,以了解它如何实现其自定义BA。具体看一下DetectComplete代码:

private void DetectComplete(object sender, DetectCompleteEventArgs e)
{
    // Parse the command line string before any planning.
    this.ParseCommandLine();
    this.root.InstallState = InstallationState.Waiting;

    if (LaunchAction.Uninstall == WixBA.Model.Command.Action)
    {
        WixBA.Model.Engine.Log(LogLevel.Verbose, "Invoking automatic plan for uninstall");
        WixBA.Plan(LaunchAction.Uninstall);
    }

您可以看到它正在检查卸载命令行选项,并立即开始卸载。