1

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>
1

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.