问题
I want to enable Upgrade in the 2nd version of our WiX custom BA installer. In my Product.wxs, Product ID is set to *, version is set to 2.0.0, and upgrade code remains the same as the 1st version's. To detect Upgrade, I used DetectRelatedBundle event handler in the Boostrapper.
The MajorUpgrade tag in the MSI looks like this:
<MajorUpgrade AllowDowngrades="no" DowngradeErrorMessage="A newer version of [ProductName] is already installed." AllowSameVersionUpgrades="no" Schedule="afterInstallInitialize" />
In my installer UI, I have an Install button. When this button is clicked during Upgrade scenario, I call PlanAction and pass LaunchAction.Install. But once installation starts, it shows another instance of BA, which I believe is the old package called by my current BA to uninstall the old version. In order to hide the new BA instance and just show installation progress, I made these changes in my 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();
}
}
Question 1) How will I let my main BA instance (the one doing installation) know that uninstallation of old package has completed? What's happening now is that it was able to successfully uninstall the old package, but no installation of the new version is being performed.
Question 2) Is my understanding of WiX upgrade correct? :)
回答1:
What is happening is your old BA is getting called in silent mode with the uninstall switch. I can see your code does have some of the plumbing to handle a command line uninstall although I can't see where you're calling Engine.Plan(LaunchAction.Uninstall).
Q1) I don't believe you have to do anything in particular to let your original BA know you're finished. You just need to exit the install in the normal way.
Q2) Yes I think you're almost there. I suggest you download the WIX source code off git to see how it implements its custom BA. Specifically look at the DetectComplete code:
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);
}
You can see it is checking for the uninstall command line option and immediately kicking off an uninstall.
来源:https://stackoverflow.com/questions/50347930/how-to-perform-wix-upgrade-with-custom-bootstrapper