我想使用 WiX 工具集 v4 中的托管引导程序应用程序创建自定义安装程序。我用来设置简单示例安装程序的教程是这样的:https://www.syncfusion.com/blogs/post/grow-from-a-newbie-to-pro-in-creating-the-installers.aspx #创建自定义用户界面安装程序 然而,在 WiX 工具集 v3 上一切正常。我尝试调整所描述的项目以在 WiX 工具集 v4 上运行。
运行安装程序时,日志显示以下错误消息:
[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.
我适应了什么? 在项目 CustomBootstrapperApplication 中: 使用 WixToolset.Mba.Core 而不是 Microsoft.Tools.WindowsInstallerXml.Bootstrapper
添加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);
}
}
}
在 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);
}
}
}
将 CustomUI.cs 重命名为 WixToolset.Mba.Host.config 并进行调整
<?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>
在 MainWindow.xaml.cs 中使用 CustomUI 类型而不是 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;
}));
}
}
}
创建了一个新的“Bundle (WiX v4)”项目 BootstrapperDefaultUI:
调整 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>
将
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
添加到 CustomBootstrapperApplication 项目,这会将另一个 dll 输出到名为 mbanative.dll. 的输出文件夹中
将 mbanative.dll 作为 PayLoad 添加到 BootstrapperApplication 中,类似于您对其他 dll 所做的操作。