Denial of installation WIX Installer - installation

I made a bootstrapper (bootstrapper is an installer that contains other installers to put all together, in this case will be my app and SQL Express database installer). When I start the bootstrapper, the SQL Express installation window is being displayed on the screen and if I close the window, my app is still set, and I need if user closes SQL Express installation window then my program won't be installed.
<?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="Bootstrapper" Version="1.0.0.0" Manufacturer="MyCompany AboutUrl="https://mycompany.ru/"
Copyright="ol raits rezervit" UpgradeCode="1788BF21-18BD-49E8-A572-DD38F9B67A88">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense"/>
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Microsoft SQL Server"
Result="exists" Variable="SQLExpressInstalled_x64" Win64="yes"/>
<Chain>
<ExePackage SourceFile="SQL2019-SSEI-Expr.exe" DetectCondition="SQLExpressInstalled_x64" Permanent="no"></ExePackage>
<MsiPackage SourceFile="MyProgram.msi"></MsiPackage>
</Chain>
</Bundle>
</Wix>

Would adding "Vital" be a usable suggestion for you?
I have added this suggestion in your provided code example as the last argument for the ExePackage.
"Vital"
Specifies whether the package must succeed for the chain to continue. The default "yes" indicates that if the package fails then the chain will fail and rollback or stop. If "no" is specified then the chain will continue even if the package reports failure.
<?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="Bootstrapper" Version="1.0.0.0" Manufacturer="MyCompany AboutUrl="https://mycompany.ru/ "Copyright="ol raits rezervit" UpgradeCode="1788BF21-18BD-49E8-A572-DD38F9B67A88">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense"/>
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Microsoft SQL Server"
Result="exists" Variable="SQLExpressInstalled_x64" Win64="yes"/>
<Chain>
<ExePackage SourceFile="SQL2019-SSEI-Expr.exe" DetectCondition="SQLExpressInstalled_x64" Permanent="no" Vital="yes"></ExePackage>
<MsiPackage SourceFile="MyProgram.msi"></MsiPackage>
</Chain>
</Bundle>
</Wix>
Ref - https://wixtoolset.org/documentation/manual/v3/xsd/wix/exepackage.html

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 to remove previous version that was installed with Bootstrapper from control panel

I've got "ABC 10.1" program version installed on computer allready and I would like to remove it on each newer ABC.msi installation (for example when ABC 10.2 is going to be installed).
So far I've used a BOOTSTRAPPER to install new versions and it worked like a charm (the previous version was uninstalled and removed from the control panel and newest was appearing in the control panel).
Right now I would like to use ABC.msi for installation and to not use the BOOTSTRAPPER, but when I use ABC.msi installer the previous one is not being removed from the control panel and I have two "ABCs" 10.1 and 10.2 versions in the control panel.
How can I remove ABC previous version that was installed by BOOTSTRAPPER during newest ABC.msi installation (and avoid duplicating ABC in Control Panel)?
Bundle.wxs
<Bundle
Name="$(var.ProductName)"
Version="$(var.ShowVersion)"
Manufacturer="ABC"
UpgradeCode="33312c8d-64f1-4a04-a98e-4aa692de6aaf"
IconSourceFile="$(var.BaseDir)\Setup\UI\ABC.ico"
Condition="((VersionNT = v6.1 AND ServicePackLevel >= 1) OR (VersionNT > v6.1)) AND (WixBundleInstalled = 0)">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication
LicenseFile="$(var.BaseDir)\Setup\UI\License.rtf"
LogoFile="$(var.BaseDir)\Setup\UI\OticonAppIcon.png"
SuppressOptionsUI="yes"
ShowVersion="yes"/>
</BootstrapperApplicationRef>
<Chain>
<!-- Install .Net 4.6.1 -->
<PackageGroupRef Id='NetFx461Redist'/>
<!-- my packages to install -->
<PackageGroupRef Id="InstallerPackages" />
</Chain>
</Bundle>
<Fragment>
<PackageGroup Id ="InstallerPackages" >
<MsiPackage SourceFile="$(var.OutDir)\ABC.MSI" />
<MsiPackage SourceFile="$(var.OutDir)\DatabaseInstallerABC.msi" />
</PackageGroup>
</Fragment>
productABC.wxs (the file that is creating ABC.msi) is as following:
<?xml version="1.0" encoding="UTF-8"?>
<?include .\defines.wxi ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension" xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="$(var.ProductCode)"
Codepage="1252" Language="1033"
Manufacturer="ABC" Name="$(var.ProductName)"
UpgradeCode="{3338CE6B-D733-41AF-830B-DCAFE2E0CD58}"
Version="$(var.ProductVersion)">
<Package Id="*"
Compressed="yes"
InstallerVersion="300"
Languages="1033"
Manufacturer="ABC"
Platform="x86" />
<Media Id="1"
Cabinet="media1.cab"
EmbedCab="yes" />
----some directories and components----
<MajorUpgrade
Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."
AllowSameVersionUpgrades="yes"/>
<InstallExecuteSequence>
<LaunchConditions After="AppSearch" />
<Custom Action="SetTargetDir" Before="CostFinalize"></Custom>
<Custom Action="SaveTargetDir" After="InstallValidate"></Custom>
</InstallExecuteSequence>
<WixVariable Id="WixUILicenseRtf" Value="$(var.BaseDir)\Setup\UI\License.rtf" />
<WixVariable Id="WixUIBannerBmp" Value="$(var.BaseDir)\Setup\UI\bannrbmp.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="$(var.BaseDir)\Setup\UI\ABCbackground.bmp" />
</Product>
</Wix>
Generic answer: The wix bootstrapper is what writes the entry in the Control Panel for your "ABC 10.1" release. In order to remove that, your 10.2 release will need to have a custom action tell the previous bundle to uninstall itself ("previous-cached-bundle.exe /silent /uninstall" or something similar). Now, whether you tell the old bundle to remove itself first, or you allow your MSI to upgrade first is up to your own requirements.

Merge two MSI into One using WIX Bootsrapper

In My application there are 2 msi installers.one is vendor supplied and cannot be modified, the other is a MSI file which i have generated using VS2010 setup and deployment.
I combined these two into one using WIX Bootstrapper,when i build this application it gives two MSIs and One Bootstrapper exe, obviously when i Click Bootstrapper exe it installs other two MSIs in a sequential manner, but the problem is I just want to give this single Bootstrapper exe to customer, but it needs other two MSIs also ,Is there any other way to do it? please find the code below..
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle Name="SoftWritersInstaller_Package" Version="1.0.0.0" Manufacturer="Microsoft" UpgradeCode="86431df1-94cc-433a-9885-af19bca9b5d3">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain >
<!-- TODO: Define the list of chained packages. -->
<!-- <MsiPackage SourceFile="path\to\your.msi" /> -->
<PackageGroupRef Id="Netfx4Full"/>
<MsiPackage Id="F_VB_AGENT" SourceFile=".\VBandMsi\Framewrk with Agent.msi" Compressed="no" EnableFeatureSelection="yes" DisplayInternalUI="yes" ></MsiPackage>
<MsiPackage Id="FVBAgent.Net" SourceFile=".\VBandMsi\.FDotNet.Setup.msi" Compressed="no" EnableFeatureSelection="yes" DisplayInternalUI="yes" />
</Chain>
</Bundle>
<Fragment>
<!-- Check for .NET 4.0 -->
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version"
Variable="Netfx4FullVersion" />
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version"
Variable="Netfx4x64FullVersion"
Win64="yes"
/>
<PackageGroup Id="Netfx4Full">
<ExePackage Id="Netfx4Full"
DisplayName="Microsoft .NET Framework 4.0"
Compressed="yes"
Cache="yes"
PerMachine="yes"
Permanent="yes"
Protocol="netfx4"
Vital="yes"
SourceFile=".\dotNetFx40_Full_x86_x64.exe"
InstallCommand="/passive /norestart"
DetectCondition="Netfx4FullVersion AND (NOT VersionNT64 OR Netfx4x64FullVersion)" />
</PackageGroup>
</Fragment>
</Wix>

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