unhandled child Wix node Bundle - macos

I am trying to create a msi with msitools on OSX.
Here is my simple xml file
<Bundle Name="some-cool-name-for-the-whole-thing"
Version="1.0"
UpgradeCode="your-guid-here">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
<bal:WixStandardBootstrapperApplication
LicenseUrl=""
ShowVersion="yes"/>
</BootstrapperApplicationRef>
<Chain>
<ExePackage Id="some_id"
SourceFile="path-to-the-setup.exe">
<CommandLine InstallArgument="/s " />
</ExePackage>
<MsiPackage Id="some-other-id-here"
SourceFile="path-to-the-MSI-you-made-for-your-app">
</MsiPackage>
</Chain>
</Bundle>
It is based on the answer here: https://stackoverflow.com/a/42102377/58129
I have installed msitools using brew. The version of msitools is 0.97.
I run the following command
wixl main.xml -o main.msi
and I get this error:
(wixl:28560): wixl-ERROR **: wix.vala:218: unhandled child Wix node Bundle
Trace/BPT trap: 5
I have tried to further simplify the xml to
I still get the same error message
Is there any problem with my xml file? Or did I invoke the command incorrectly?

wixl doesn't support bundles. You can see the source code over at https://github.com/GNOME/msitools/tree/master/tools/wixl.

Related

WIX Toolset Bundle does not detect package that was just installed

I am creating a super simple bootstrapper project that installs just 1 MSI.
Install works perfectly, but when I do an uninstall from (ARP), the package just installed is not detected, so it is not removed, but the bootstrapper is removed from ARP, making it seem like the product is gone.
I have to run the EXE again, which makes it seem like an install is happening, but when the MSI is executed, it shows the options to change or remove the product (as is expected).
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="Bed Occupancy Monitoring"
Version="$(var.PRODUCTVERSION)"
Manufacturer=""
UpgradeCode="4346DC9B-5B4D-4301-A8A6-EE4ED4C001DB">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
<bal:WixStandardBootstrapperApplication
LicenseUrl=""
ThemeFile="HyperlinkLargeTheme.xml"
LocalizationFile="HyperlinkTheme.wxl"
LogoFile="Logo.png"
SuppressOptionsUI="yes"
ShowVersion="yes"/>
</BootstrapperApplicationRef>
<Chain>
<MsiPackage Id="BedOccupancy"
SourceFile="$(var.Installer.TargetPath)"
DisplayName="Bed Occupancy $(var.PRODUCTVERSION)"
DisplayInternalUI="yes"
Permanent="no"
Visible="no"/>
</Chain>
</Bundle>
</Wix>

WiX Burn Bundle Installer Returns ERROR_SUCCESS_REBOOT_REQUIRED - 3010 (0xBC2) Upon Installation Failure

When one of MSI packages chained in my WiX bundle fails to install, the bundle installer rolls back other MSI packages that have been processed up to that point and then returns ERROR_SUCCESS_REBOOT_REQUIRED - 3010 (0xBC2), which means "the requested operation is successful. Changes will not be effective until the system is rebooted." Given that some of the MSI packages in the bundle require reboot after installation or uninstallation, it's expected that the return code indicates that a reboot is required regardless of whether the installation is successful or not. However, in the above situation, I was expecting the return code to be ERROR_FAIL_REBOOT_REQUIRED - 3017 (0xBC9) because the installation failed, and I'm confused as to why I'm getting 'success' instead.
Here is a snippet of a log generated by the bundle installer that shows that the installer is aware of a failed result:
[0E04:0BA4][2022-03-31T15:56:20]i399: Apply complete, result: 0x80070643, restart: Required, ba requested restart: No
[0E04:0BA4][2022-03-31T15:56:20]i500: Shutting down, exit code: 0xbc2
For reference, my WiX script for the bundle installer is written something like this:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle Name="..." Version="..." UpgradeCode="..." Manufacturer="...">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
<bal:WixStandardBootstrapperApplication LicenseUrl="" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" />
</BootstrapperApplicationRef>
<Chain>
<MsiPackage SourceFile="..." />
<MsiPackage SourceFile="..." />
<MsiPackage SourceFile="..." />
<MsiPackage SourceFile="..." />
<MsiPackage SourceFile="..." />
</Chain>
</Bundle>
</Wix>
Am I doing something wrong, or is this a bug in WiX?
I confirmed that the failed MSI package returns ERROR_INSTALL_FAILURE - 1603 (0x643) upon installation failure when executed individually using MsiExec, which matches the result code logged from the bundle installer (0x80070643).
The line of code doing this is in WixStandardBootstrapperApplication.cpp(1140):
// initiate engine shutdown
DWORD dwQuit = HRESULT_CODE(hr);
if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult)
{
dwQuit = ERROR_SUCCESS_REBOOT_INITIATED;
}
else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult)
{
dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED;
}
pThis->m_pEngine->Quit(dwQuit);
Looking at that code sees restart required and returns that result without considering if a failure was also involved. Seems like a reasonable feature request you could look to implement in WiX v4.

collision in wix extension: NetFxExtension

I am trying to create a bootstrapper project in Visual Studio 2015 using Wix.
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="..." Version="1.0.0.0" Manufacturer="..." UpgradeCode="...">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="mtel-eula-free.rtf"/>
</BootstrapperApplicationRef>
<BootstrapperApplicationRef Id="WixBootstrapperApplication:WixNetFxExtension" />
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost">
<Payload
Name="BootstrapperCore.config"
SourceFile="$(var.TargetDir)\BootstrapperCore.config"/>
<Payload
SourceFile="$(var.TargetPath)"/>
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx45Web"/>
<MsiPackage Id="MTESetup" SourceFile="$(var.MTESetup.TargetPath)"/>
</Chain>
</Bundle>
</Wix>
The project name for the bootstrapper is MTEBootstrapper and the project name for the wix project for the MSI is MTESetup. For MTEBootstrapper, I added a reference to WixNetFxExtension.dll from Wix 3.10; In the properties of MTEBootstrapper, I added -ext WixNetFxExtension.dll. Now I am getting this error when I try to build MTEBootstrapper:
Error The extension 'Microsoft.Tools.WindowsInstallerXml.Extensions.NetFxExtension' contains a defintion for table 'NetFxNativeImage' that collides with a previously loaded table definition. Please remove one of the conflicting extensions or rename one of the tables to avoid the collision. MTEBootstrapper light.exe 0
I have no idea what is causing this. How do I fix it?
It looks like this error surfaces when I have both the reference to WixNetFxExtension added to MTEBootstrapper and the -ext option for the linker. I removed the -ext option for the linker and collision error disappeared.
(Separately I am getting an unresolved symbol WixNetFxExtension, which I will file a separate question for.)

Is there a way to make an installer which can install multiple msis downloading from internet?

Just like WiX installer, I wanna distribute a small setup.exe, while installing, the setup.exe can download the demanded msis from a specified server.
If anyone know how to do, code sample is better.
The below codes can be compiled successfully, but the WixBA UI doesn't display.
<?xml version="1.0" encoding="UTF-8"?>
<BootstrapperApplicationRef Id='ManagedBootstrapperApplicationHost'>
<Payload Name='BootstrapperCore.config' SourceFile='WixBA.BootstrapperCore.config' />
<Payload SourceFile='WixBA.dll' />
<Payload SourceFile='License.htm' />
</BootstrapperApplicationRef>
<Variable Name='InstallFolder' Type='string' Value='[ProgramFilesFolder]Test' />
<Chain>
<MsiPackage Id='sevenz' Vital='yes' Name='data\7z.msi' SourceFile='data\7z.msi' >
<MsiProperty Name='INSTALLFOLDER' Value='[InstallFolder]' />
</MsiPackage>
</Chain>
</Bundle>
The WiX toolset supports this using the Burn engine. The source code is all available in src\burn\engine (in particular, you'll want to look at downloadengine.cpp).

WiX Bundle bal:condition - util:RegistrySearch variable always false

I want my install to fail if a third-party software element is not installed. I added a Fragment with a util:RegistrySearch and a bal:Condition to the Bundle, but I can't get it to work. ThirdPartyCOMLibraryInstalled never evaluates to true. I've confirmed that the key exists, and the value I use for Key is correct - I copy/pasted the name from the selected key in regedit. There aren't any errors in the log.
I'm building the installer with WiXTools 3.7 in Visual Studio 2012 on Windows 7 64-bit and testing on both Windows XP SP3 and Windows 7 64-bit.
Searching online for other examples for util:RegistrySearch I ran across the following alternative forms for the condition test expression.
ThirdPartyCOMLibraryInstalled = 0 - always False
ThirdPartyCOMLibraryInstalled <> 1 - always True
Here is the Bundle code:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="!(bind.packageName.MyApp)"
Version="!(bind.packageVersion.MyApp)"
Manufacturer="!(bind.packageManufacturer.MyApp)"
UpgradeCode="a07ce1d5-a7ed-4d89-a7ee-fb13a5dd69ba"
Copyright="Copyright (c) 2013 [Bundle/#Manufacturer]. All rights reserved."
IconSourceFile="$(var.My_Application1.ProjectDir)MyCo.ico">
<bal:Condition Message="ThirdParty Application COM Library Required. Please (re)install ThirdParty Application and ensure 'Windows API' and '.NET Components' are installed."
>ThirdPartyCOMLibraryInstalled</bal:Condition>
<Variable Name="InstallFolder"
Type="string"
Value="[ProgramFilesFolder]MyCo Systems\My_Application\"/>
<BootstrapperApplicationRef
Id="WixStandardBootstrapperApplication.HyperlinkLicense" >
<bal:WixStandardBootstrapperApplication
ThemeFile="Resources\HyperlinkTheme.xml"
LaunchTarget="[InstallFolder]My_Application.exe"
LocalizationFile="Resources\HyperlinkTheme.wxl"
SuppressRepair="yes"
SuppressOptionsUI="yes"
LicenseUrl=""
LogoFile="Resources/MyCoLogoWt64.png"
/>
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx40Redist"/>
<MsiPackage Id ="MyApp"
Vital="yes"
Name="My Application"
SourceFile="$(var.MyApp_Install.TargetDir)MyApp_Install.msi">
<MsiProperty Name="INSTALLLOCATION"
Value="[InstallFolder]" />
</MsiPackage>
</Chain>
</Bundle>
<Fragment>
<util:RegistrySearch
Variable="ThirdPartyCOMLibraryInstalled"
Result="exists"
Root="HKLM"
Key="SOFTWARE\Classes\ThirdPartyId.Server\CLSID"/>
</Fragment>
</Wix>
The root issue is that the RegistrySearch is in a separate Fragment that never gets referenced. Because nothing in the Fragment gets referenced the linker "optimizes away" the contents of the Fragment and the search is not included in your Bundle.
Aside: you could argue that the fact that there is a reference to the variable mentioned in the search in the Condition that the linker should be able to figure out that the search is necessary. However, that doesn't work out in all cases.
Fortunately, the solution is quite simple! You even have to choose from one of two:
Move the RegistrySearch element to the Bundle element.
Add a RegistrySearchRef element in the Bundle element to reference the RegistrySearch in the Fragment. You will also need to give the RegistrySearch and Id attribute.
Personally, I like option two and I would probably even move the Condition into the Fragment as well to group all that stuff together. Something akin to:
<Bundle ...>
<util:RegistrySearchRef Id='SearchForThirdParty' />
...
</Bundle>
<Fragment>
<util:RegistrySearch
Id='SearchForThirdParty'
Variable="ThirdPartyCOMLibraryInstalled"
Result="exists"
Root="HKLM"
Key="SOFTWARE\Classes\ThirdPartyId.Server\CLSID"/>
<bal:Condition Message="ThirdParty Application COM Library Required. Please (re)install ThirdParty Application and ensure 'Windows API' and '.Net Components' are installed.">ThirdPartyCOMLibraryInstalled</bal:Condition>
</Fragment>
</Wix>
That should do it.

Resources