WiX Bundle bal:condition - util:RegistrySearch - Not working - wix

A similar post is up here but I cant get mine working
WiX Bundle bal:condition - util:RegistrySearch variable always false
Sir, I am struggling get this exact thing working. "Version" is set to 0 when Registry key is absent and to 1 when key is present. Either cases my bundle still gets installed.
I am using VS 2015 and Wix 3.10. Pls can you help.
<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="XXX"
Version="XXX"
Manufacturer="XXX"
UpgradeCode="XXX"
IconSourceFile="XXX"
Copyright="XXX" >
<util:RegistrySearchRef Id='SearchForMyIns' />
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost">
...
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id='NetFx40Web' />
<MsiPackage SourceFile="$(var.DummyInstaller.TargetDir)\DummyInstaller.msi" DisplayName="Dummy Conditioning" />
</Chain>
</Bundle>
<Fragment>
<util:RegistrySearch
Id='SearchForMyInst'
Variable="Version"
Result="exists"
Root="HKLM"
Key="SOFTWARE\MyInst"
Win64="yes" />
<bal:Condition Message="ThirdParty Application Required.">Version</bal:Condition>
</Fragment>
</Wix>

The Bal:Condition doesn't evaluate if you are using MBA. Check the following link
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Wix-Burn-Bundle-condition-does-not-work-if-using-MBA-td7581757.html
Change
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost">
to
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
You will see Bal:Condition working

The reason this is always installing for you is that
<bal:Condition Message="messagehere">Version</bal:Condition>
will evaluate the existance of Version not the value of Version. Since your registry search is on exists, Version is always defined and thus the condition always passes. (I believe this is because all registry search variables are implicitly string variables)
If you add "Version = 1" then your installation should only continue when your registry search does find what you're looking for.
I would also like to point out a particularly nasty pitfall of this type of condition. What happens if a user installs your bundle then decides they don't need your bundle or the third party program anymore and they uninstall them both but they uninstall the third party program first?
Your installer will be unable to uninstall because when it tries to run it will fail the bal:Condition every time since the third party program is no longer present on the system.
To solve this behaviour you should add "OR WixBundleInstalled" to your bal:Condition.

Related

Entry for WiX bundle is not removed from the ARP list when uninstalled via UpgradeVersion element

Our application is installed using a WiX bootstrapper. Consequently, the Windows 10 Apps and Features list (a.k.a. ARP) shows an entry for the bundle, and another entry for the .msi which is contained within it.
On my system, I have OurApp v.9.0 installed, as well as v.9.1 Beta. When I install the upgrade, v.9.1 Full Release, it is seen as an upgrade to v.9.0, which is automatically uninstalled. v.9.1 Beta is also uninstalled by use of the following code:
<!-- Uninstall Beta Version [only use this for Full Release] -->
<?if Not $(var.Phase) = "Beta" ?>
<Upgrade Id='233E450E-182F-4823-9C24-2F28A93A52A8'>
<UpgradeVersion OnlyDetect='no' Property='OLDINSTALLER' Minimum='0.0.0' />
</Upgrade>
<?endif?>
Unfortunately, the entry for OurApp 9.1 Beta bundle is sometimes left behind in the ARP list after uninstalling. (The OurApp 9.1 Beta .msi package was successfully removed from the ARP list.) If I try to uninstall the Beta bundle again, it simply disappears without really doing anything. Usually, uninstalling the app from ARP will cause some uninstallation dialogs to appear, but in this case, they don't appear, the entry is simply removed from ARP.
I have looked at the following posts for guidance:
WiX upgrade didn't remove the earlier product from ARP
MSI uninstall does not remove product entry in program features
After using msiexec to uninstall a program it remains in the control panel (add/remove programs)
Unfortunately, these don't seem to be describing quite the same situation as I'm seeing, and I don't understand the suggestions well enough to determine what to do in our case. I did happen to see this comment:
"Duplicate installations are very common in such cases as a by-product of rapid test cycles."
Since "rapid test cycles" would describe well our situation, I'm wondering if this might be the case for us. However, I have 2 difficulties:
I don't understand how to confirm that this is happening or what to do about it.
I get the impression that this would be unlikely to occur on an end-user's system, since they are not participating in these "rapid test cycles". Do we actually need to do anything?
I would appreciate any input / advice on dealing with this situation.
UPDATE:
Here is the WiX code for building our bundle:
<?xml version="1.0"?>
<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"
xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
<Bundle
Name='UsefulApp $(var.TruncatedVersion) $(var.Phase)'
Version='$(var.VersionNumber)'
UpgradeCode='$(var.UpgradeCode)'
Tag='UsefulFrmwrkBndl'
IconSourceFile='$(var.UsefulInstallIcon)'
Copyright="Copyright ©$(var.CurrentYear), $(var.ProducedBy). All Rights Reserved."
Manufacturer='$(var.ProducedBy)'>
<bal:Condition Message="32-bit Windows is no longer supported."> (VersionNT64 >= v6.0) </bal:Condition>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
<Payload SourceFile="UsefulLicense.htm" />
</BootstrapperApplicationRef>
<!--<RelatedBundle Id='$(var.UpgradeCode)' Action='Detect'/>-->
<WixVariable Id="WixStdbaLicenseUrl" Value="UsefulLicense.htm" />
<WixVariable Id="WixStdbaLogo" Value=".\resources\image_option_1.bmp" />
<WixVariable Id="WixStdbaThemeXml" Value="UsefulHyperlinkTheme.xml" />
<WixVariable Id="WixStdbaThemeWxl" Value="UsefulHyperlinkTheme.wxl" />
<Chain>
<PackageGroupRef Id="NetFx48" />
<PackageGroupRef Id="redist_vc14" />
<RollbackBoundary />
<PackageGroupRef Id='UsefulFrameworkPackGroup'/>
</Chain>
</Bundle>
<Fragment Id='UsefulFrag'>
<PackageGroup Id='UsefulFrameworkPackGroup'>
<MsiPackage Id='UsefulMsiPack'
DisplayName='UsefulApp $(var.VersionNumber)'
DisplayInternalUI='yes'
ForcePerMachine='yes'
InstallCondition='1'
SourceFile='UsefulApp_$(var.VersionNumber)_Installer.msi'
Visible='yes'
Vital='yes'>
</MsiPackage>
</PackageGroup>
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version" Variable="Netfx48FullVersion" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version" Variable="Netfx48x64FullVersion" Win64="yes" />
</Fragment>
</Wix>

WiX Bundle not displaying MSIs in Programs and Features

I've got new, weird behavior in my bundle installation: the MSIs -- which used to appear in Programs and Features -- have stopped appearing in Programs and Features (hereafter referred to as P&F).
The behavior that I'd like to happen is for the programs that I install as MSIs to appear in P&F, giving the user the chance to uninstall them discretely.
What I've tried/noticed:
If I install the MSIs without bundling them:
they appear in P&F, and are able to be uninstalled
moreover, I can control whether they appear in P&F by setting the ARPSYSTEMCOMPONENT property to either 1 (default is 0, meaning "do appear in P*F), that is:
<Property Id="ARPSYSTEMCOMPONENT" Value="1"/>
these changes are reflected in the registry. When examining the key HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/{GUID}, if I set the property to 1 it shows up (it doesn't show up when I set it to 0, but I think that's because defaults don't show up).
However, when I put the MSIs into a Bundle, bingo-bango-bongo they disappear from P&F! And, if I check the registry, the SystemComponent property is set to 1 for each MSI.
I'm reaching the conclusion that somehow, in my bootstrapper, the SystemComponent properties for my MSIs are being set to 1. But where could these properties be set? Needless to say, I never set them in my WiX XML (at least, I don't think I do). I don't have any special UI for the bootstrapper (just a license), and the MSIs themselves install quietly, with no UI.
I'm stuck! Can anyone shed some light on this?
I'm using Visual Studio 2015, WiX version 3.10. Here's the entirety of my Bootstrapper code:
<?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"
xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">
<Bundle Name="****"
Version="1.0.5.0"
Manufacturer="****"
UpgradeCode="7be91f26-93f8-400c-9eac-e69383454e03"
IconSourceFile="src\****.ico" DisableModify="yes" DisableRemove="yes"
AboutUrl="****.com"
Copyright="Copyright 2017, ****">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="src\****_License.rtf"
SuppressOptionsUI="yes"/>
</BootstrapperApplicationRef>
<!-- The two registry serarches provide a variable, what version of .NET is installed on the target machine. One search
is for x86, the other for x64. -->
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version"
Variable="Net452FullVersion"/>
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version"
Variable="Net452x64FullVersion"
Win64="yes"/>
<Chain>
<ExePackage
Id="Microsoft_dot_Net_4.5.2"
Name="Microsoft 4.5.2 Setup"
Cache="no"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
SourceFile="executables\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
InstallCommand="/q"
DetectCondition="(Net452FullVersion = "4.5.51209") AND (NOT VersionNT64 OR (Net4x64FullVersion = "4.5.51209"))"
InstallCondition="(VersionNT >= v6.0 OR VersionNT64 >= v6.0) AND (NOT (Net452FullVersion = "4.5.51209" OR Net452x64FullVersion = "4.5.51209"))"/>
<ExePackage Id="Microsoft_Visual_C_plus_plus_Redistributable_2015"
InstallCommand="/q"
SourceFile="executables\vc_redist.x86.exe"/>
<RollbackBoundary/>
<MsiPackage SourceFile="$(var.****.TargetPath)"/>
<MsiPackage SourceFile="$(var.****.TargetPath)"/>
<ExePackage SourceFile="executables\****.exe" InstallCommand="/S"/>
<ExePackage SourceFile="executables\****.exe"/>
</Chain>
</Bundle>
</Wix>
The MsiPackage/#Visible attribute controls whether MSI packages are shown in ARP.

WIX - How to selectively uninstall the <Bundle>

I want to retain the previous versions of my Bootstrapper App, how to achieve this?
I know that we can use the Upgrade tag in MSI where we can identify the different versions and perform uninstall operations base on those.
Now, I have a Bundle Application that has one or more MSI which use some UpgradeCode. Each time I create a new build I just version up the MSI and this Bundle Application. When I proceed with installing of later version of Bundle App, it uninstall the previous Bundle version, which is not what I want. I want to retain the previous versions of my Bundle Application.
Is there anything like UpgradeVersion in Bundle as well, where we would be able to identify the diferent versions and do selectively uninstall.
My Bundle file code snippet :
<Bundle Name="myApp"
Version="1.0.0.0"
Manufacturer="Myself"
UpgradeCode="SOME-GUID">
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" >
...
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id= 'WindowsInstaller45'/>
<PackageGroupRef Id ='NetFx45Offline'/>
<PackageGroupRef Id ='MY_MSI'/>
</Chain>
</Bundle>
<Fragment Id ='PkgFragments'>
<PackageGroup Id ="MY_MSI">
<MsiPackage SourceFile= "$(var.Installer.TargetPath)"
Id="MYAPP"
Cache ="yes"
Visible ="no"
DisplayInternalUI ="no"
Permanent="no">
<MsiProperty Name='INSTALLLOCATION' Value='[InstallFolder]' />
<MsiProperty Name='SELECT_UNINST' Value='[UninstallPrevVersion]' />
</MsiPackage>
</PackageGroup>
</Fragment>
My Product WIX file code snippet
<Product Id="*"
Name="$(var.ProductName)"
Version="$(var.ProductVersion)"
Manufacturer="$(var.ManufacturerName)"
UpgradeCode="$(var.UpgradeCode)">
<Property Id="SELECT_UNINST" Secure="yes">1</Property>
<Upgrade Id="SOME-GUID2">
<UpgradeVersion Minimum="0.0.0.0" Maximum="$(var.ProductVersion)" IncludeMinimum="yes" IncludeMaximum="yes" Property="UNINSTALL_PREV_VERSION" />
</Upgrade>
<CustomAction Id="UninstPrev" Property="UNINSTALL_PREV_VERSION" Value="0" />
<InstallExecuteSequence>
<Custom Action="UninstPrev" Before="InstallInitialize"><![CDATA[SELECT_UNINST <> 1]]></Custom>
<RemoveExistingProducts Overridable="no" After="UninstPrev"></RemoveExistingProducts>
</InstallExecuteSequence>
</Product>
I'll put this as an answer too.
If you don't want to remove your previous versions don't treat the new version as an upgrade to the old one. This means change the upgrade GUID and change the product GUID. If you need to remove a specific version, add the bundle as a <RelatedBundle> in your Bundle definition and properly handle OnPlanRelatedBundle in your Bootstrapper Application.
<RelatedBundle Action="Detect" Id="$(var.ProductVersion622UpgradeGUID)"/>
Additionally, any msi packages you install also would need to employ the same behaviour of new upgrade GUIDs if you don't want removal between "upgrades". Keep a list of which GUIDs are with which released versions. If you want to remove specific versions in a release of your msi you need to add
<Upgrade Id="$(var.Version6InstallerUpgradeGUID)" >
<UpgradeVersion
IncludeMaximum ="no"
IncludeMinimum="yes"
Maximum="6.0.0.1"
Minimum="6.0.0.0"
MigrateFeatures="no"
Property="V6FOUND"
OnlyDetect="no" />
</Upgrade>
I would consider this requirement very odd and would suggest you really think upon whether or not you really want to support this kind of behaviour.
Also to note, the entry in the ARP for the bootstrapper existing doesn't necessarily mean the products it installed are still on the system. You can test this by always setting pRequestedState = RequestState.Present; in OnPlanRelatedBundle and setting your msi packages to visible="yes". You will have the old bundle listed in the ARP but the packages it installs were probably upgraded by the newer version so it's just an entry that doesn't mean anything.

How to check in WiX, if IIS-Feature is installed?

I have programmed a Bootstrapper-project with WiX 3.8, in which i'm installing IIS Express 8.0 and activating some IIS-Features.
The activation lies in a seperate WXS-file - including a lot of ExePackages - like that:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<PackageGroup Id='ActivateIisFeatures'>
<ExePackage Id='IIS_WebserverRole'
DisplayName='Installing IIS: IIS-WebServerRole'
PerMachine='yes'
SourceFile='.\Resources\Dism.exe'
InstallCommand='/Online /Enable-Feature /FeatureName:IIS-WebServerRole'>
</ExePackage>
...
</PackageGroup>
...
</Fragment>
</Wix>
Now my problem is, that by this way, the ExePackages will be installed and the features activated everytime, the setup is installed or repaired.
So i tried the DetectCondition-Property.
You know, if the DetectCondition returns false, the Bootstrapper plans to install the ExePackage.
But the following edit does still install the ExePackages everytime, even when the features are active.
What have i to do, that the IIS-features will only installed/activated, when they are not active?
Thanks in advance!
Okay, i have found it out myself.
It's really simple.
DetectCondition doesn't work here.
We have to search for the registrykey and check the result in the Installcondition of the ExePackage.
Most of the keys are lying in the folder "HKLM\SOFTWARE\Microsoft\InetStp\Components".
And there is a list on the iis-site, but it's old and not complete:
http://www.iis.net/learn/install/installing-iis-7/discover-installed-components
Per example:
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Microsoft\InetStp\Components"
Value="W3SVC"
Variable="WebServer"/>
<ExePackage Id='IIS_WebServer'
DisplayName='Installing IIS: IIS-WebServer'
PerMachine='yes'
SourceFile='.\Resources\Dism.exe'
InstallCondition='NOT WebServer'
InstallCommand='/Online /Enable-Feature /FeatureName:IIS-WebServer'>
</ExePackage>
By this way, once a features was activated, it doesn't happen anymore while reinstalling or repairing the setup.

WiX Burn: Reading LaunchTarget from Registry

I'm new with WiX, and I'm trying to have my Bootstrapper launch my installed application when it completes. To accomplish this, I'm using
<Variable Name="LaunchTarget" Value="path_to_exe"/>
However, it is not easy for me to get the path to the executable. The reason for this is because I'm using <Chain> to install some pre-requisites and then an msi that actually installs my exe.
So to do this, the msi is writting the path to a known location in the registry, and then the bootstrapper reads it and uses it.
The problem is that when the bootstrapper reads the registry, the msi hasn't run yet, so it is unable to run the executable at the end.
Here's my WiX, if it helps:
<?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="My Installation" UpgradeCode="a8964402-f3fc-4878-aafd-31ecda6b685e" Version="1.0.0.0">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="EULA.rtf"
ThemeFile="theme.xml"
SuppressOptionsUI="yes" />
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx40Redist"/>
<ExePackage Id="OpenSSL" SourceFile="pre-requesite.exe" />
<MsiPackage Id="myInstall" SourceFile="mySetup.msi" />
</Chain>
<util:RegistrySearch Root="HKLM"
Key="Software\myProgram"
Value="myEXEPath"
Variable="myEXEPath"
Result="value"
Format="raw" />
<Variable Name="LaunchTarget" Value="[myEXEPath]"/>
</Bundle>
</Wix>
So, in short, I'm trying to have the RegistrySearch run AFTER the MsiPackage installs. Can this be done? If not, what alternatives do I have?
As I side note, if I manually fill in the registry value before installation, everything works fine. This means that besides the order things are running in, everything is working fine.
RegistrySearches run during the Detect operation. Custom BAs could run Detect after Apply, but that's not really an option since you're using the WixStandardBootstrapperApplication.
Lucky for you, WiX v3.9 added support for running the LaunchTarget already elevated, with the requirement that the path to the target .exe be in the registry under HKLM. So you would do this:
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="EULA.rtf"
ThemeFile="theme.xml"
SuppressOptionsUI="yes"
LaunchTargetElevatedId="MyAEEId" />
</BootstrapperApplicationRef>
<ApprovedExeForElevation Id="MyAEEId"
Key="Software\myProgram" Value="myEXEPath" />
Edit:
It looks like you are required to set LaunchTarget as well. Why doesn't your bundle know where it will be? You can just put in gibberish for LaunchTarget (WixStdBA will try the registry location first), but can't you use built-in variables and/or MsiProperty elements to locate the exe?