Reputation: 11
I want to create a custom installer with Managed Bootstrapper Application in WiX toolset v4. The tutorial what I used to setup a simple example installer was this: https://www.syncfusion.com/blogs/post/grow-from-a-newbie-to-pro-in-creating-the-installers.aspx#creating-a-custom-ui-installer However, on the v3 of the WiX toolset everything works fine. I tried to adapt the described projects to run on WiX toolset v4.
When running the installer, the log shows this error messages:
[3264:2A08][2023-07-21T11:57:09]i000: Loading managed bootstrapper application.
[3264:2A08][2023-07-21T11:57:09]e000: Error 0x80131524: Failed to create the bootstrapper application.
[3264:2A08][2023-07-21T11:57:09]e000: Error 0x80131524: Failed to create the managed bootstrapper application.
[3264:2A08][2023-07-21T11:57:09]e000: Error 0x80131524: Failed to create BA.
[3264:2A08][2023-07-21T11:57:09]e000: Error 0x80131524: Failed to load BA.
[3264:2A08][2023-07-21T11:57:09]e000: Error 0x80131524: Failed while running
[3264:2A08][2023-07-21T11:57:09]i502: Cleanup begin.
What did I adapt? In Project CustomBootstrapperApplication: using WixToolset.Mba.Core instead of Microsoft.Tools.WindowsInstallerXml.Bootstrapper
add CustomUI.Factory.cs
[assembly: WixToolset.Mba.Core.BootstrapperApplicationFactory(typeof(CustomBootstrapperApplication.CustomUIFactory))]
namespace CustomBootstrapperApplication
{
using WixToolset.Mba.Core;
public class CustomUIFactory : BaseBootstrapperApplicationFactory
{
protected override IBootstrapperApplication Create(IEngine engine, IBootstrapperCommand command)
{
return new CustomUI(engine);
}
}
}
In CustomUI.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using WixToolset.Mba.Core;
namespace CustomBootstrapperApplication
{
public class CustomUI : BootstrapperApplication
{
public CustomUI(IEngine engine) : base(engine)
{
}
public IEngine Engine => this.engine;
public static Dispatcher BootstrapperDispatcher { get; private set; }
// public static MainWindow view;
protected override void Run()
{
this.Engine.Log(LogLevel.Verbose, "Launching Custom UI");
BootstrapperDispatcher = Dispatcher.CurrentDispatcher;
MainWindow view = new MainWindow(this);
view.Bootstrapper.Engine.Detect();
view.DataContext = view;
view.Closed += (sender, e) => BootstrapperDispatcher.InvokeShutdown();
view.Show();
Dispatcher.Run();
this.Engine.Quit(0);
}
}
}
rename CustomUI.cs to WixToolset.Mba.Host.config and adapt
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="wix.bootstrapper" type="WixToolset.Mba.Host.BootstrapperSectionGroup, WixToolset.Mba.Host">
<section name="host" type="WixToolset.Mba.Host.HostSection, WixToolset.Mba.Host" />
</sectionGroup>
</configSections>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<wix.bootstrapper>
<host assemblyName="CustomBootstrapperApplication">
</host>
</wix.bootstrapper>
</configuration>
In MainWindow.xaml.cs using type CustomUI instead of BootstrapperApplication
using System;
using System.Collections.Generic;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WixToolset.Mba.Core;
namespace CustomBootstrapperApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private bool isInstall;
/// <summary>
/// Initializes a new instance of the MainView class.
/// </summary>
public MainWindow(CustomUI bootstrapper)
{
InitializeComponent();
this.Bootstrapper = bootstrapper;
this.Bootstrapper.DetectPackageComplete += this.OnDetectPackageComplete;
this.Bootstrapper.PlanComplete += this.OnPlanComplete;
this.Bootstrapper.ExecuteProgress += this.OnExecuteProgress;
this.Bootstrapper.ExecuteComplete += this.OnExecuteComplete;
this.Bootstrapper.ExecuteBegin += this.OnExecuteBegin;
}
public CustomUI Bootstrapper { get; private set; }
private void Exit_Button_Click(object sender, RoutedEventArgs e)
{
CustomUI.BootstrapperDispatcher.InvokeShutdown();
}
private void Install_Button_Click(object sender, RoutedEventArgs e)
{
isInstall = true;
Install_Button.Visibility = Visibility.Collapsed;
process.Content = "Waiting to Install...";
Bootstrapper.Engine.Plan(LaunchAction.Install);
}
private void Uninstall_Button_Click(object sender, RoutedEventArgs e)
{
isInstall = false;
Uninstall_Button.Visibility = Visibility.Collapsed;
process.Content = "Waiting to Uninstall...";
Bootstrapper.Engine.Plan(LaunchAction.Uninstall);
}
private void OnExecuteComplete(object sender, ExecuteCompleteEventArgs e)
{
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
delegate ()
{
if (isInstall)
{
process.Content = "Installed";
}
else
{
process.Content = "Uninstalled";
}
}));
}
private void OnExecuteBegin(object sender, ExecuteBeginEventArgs e)
{
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
delegate ()
{
if (isInstall)
{
process.Content = "Installing...";
}
else
{
process.Content = "Uninstalling...";
}
}));
}
private void OnDetectPackageComplete(object sender, DetectPackageCompleteEventArgs e)
{
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
delegate ()
{
if (e.PackageId == "Sample")
{
if (e.State == PackageState.Absent)
{
Install_Button.Visibility = Visibility.Visible;
Uninstall_Button.Visibility = Visibility.Collapsed;
}
else if (e.State == PackageState.Present)
{
Uninstall_Button.Visibility = Visibility.Visible;
Install_Button.Visibility = Visibility.Collapsed;
}
}
}));
}
private void OnPlanComplete(object sender, PlanCompleteEventArgs e)
{
if (e.Status >= 0)
Bootstrapper.Engine.Apply(System.IntPtr.Zero);
}
private void OnExecuteProgress(object sender, ExecuteProgressEventArgs e)
{
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
delegate ()
{
progressBar.Value = e.ProgressPercentage;
}));
}
}
}
Created a new "Bundle (WiX v4)" Project BootstrapperDefaultUI:
adapt the Bundle.wxs
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
<Bundle Name="BootstrapperDefaultUI" Manufacturer="TODO Manufacturer" Version="1.0.0.0" UpgradeCode="7ee73ecd-5bb0-47e1-9e9b-25883e076b17">
<BootstrapperApplication>
<Payload SourceFile="..\CustomBootstrapperApplication\bin\Debug\CustomBootstrapperApplication.dll" />
<Payload SourceFile="..\CustomBootstrapperApplication\bin\Debug\CustomBootstrapperApplication.dll.config" />
<Payload SourceFile="..\CustomBootstrapperApplication\bin\Debug\CustomBootstrapperApplication.pdb" />
<Payload SourceFile="..\CustomBootstrapperApplication\bin\Debug\WixToolset.Mba.Core.dll" />
<Payload SourceFile="..\CustomBootstrapperApplication\bin\Debug\WixToolset.Mba.Core.xml" />
<Payload SourceFile="..\CustomBootstrapperApplication\bin\Debug\WixToolset.Mba.Host.config" />
<bal:WixManagedBootstrapperApplicationHost />
</BootstrapperApplication>
<Chain>
<MsiPackage SourceFile="..\SampleWixApplication\bin\x86\Debug\en-US\SampleWixApplication.msi" bal:PrereqPackage="yes" />
</Chain>
</Bundle>
</Wix>
Upvotes: 1
Views: 1150
Reputation: 11
Add <RuntimeIdentifier>win-x64</RuntimeIdentifier>
to CustomBootstrapperApplication project this will output another dll into your output folder called mbanative.dll.
Add mbanative.dll as PayLoad into your BootstrapperApplication, similar to what you did to the other dlls.
Upvotes: 1