WiX - compare String with <property> in <?if ?> <? else ?> statement - properties

Hey Guys hopefully somebody could help me with this problem. I am trying to compare the value of an Property with an String which is manually defined.
I am not sure if it should work like this here is my Code.
<Variable Name="VS2013Installed" />
<Variable Name="VS2015Installed" />
<!-- Should Search the Registry for the Keys -->
<!-- Searches for the Key of Visual Studio 2013 -->
<Property Id="VS2013" Secure="yes" >
<RegistrySearch Id="SEARCH_VS2010" Type="raw" Root="HKCR" Key="VisualStudio.accessor.12.0\shell\Open\ddeexec\Application" >
</RegistrySearch>
</Property>
<!-- Searches for the Key of Visual Studio 2015 -->
<Property Id="VS2015" Secure="yes" >
<RegistrySearch Id="SEARCH_VS2015" Type="raw" Root="HKCR" Key="VisualStudio.accessor.14.0\shell\Open\ddeexec\Application" >
</RegistrySearch>
</Property>
<!-- Should compare the value of the property with the String-->
<?if [VS2013] = "VisualStudio.12.0" ?>
<?define VS2013Installed= "1" ?>
<?else ?>
<?define VS2013Installed= "0" ?>
<?endif?>
<!-- Should compare the value of the property with the String-->
<?if [VS2015] = "VisualStudio.14.0" ?>
<?define VS2015Installed= "1" ?>
<?else ?>
<?define VS2015Installed= "0" ?>
<?endif?>
<!-- This Condition is only here to get an Message Window with the values of the variables-->
<Condition Message="$(var.VS2013Installed)$(var.VS2015Installed)">
<![CDATA[0 = 1 ]]>
</Condition>
As a result of the Condition I am getting: 0,0

WiX conditional compilation is for WiX variables. You want conditions on Windows Installer properties. It looks like you have a handle on setting properties and using property expressions; just make it all properties and conditions. (Your use of WiX define and var is fine, though.)
You are using the WiX Toolset to build a Windows Installer package (.msi file). A Windows Installer package is a relational database as you can see visually with tools like InstEd. The Windows Installer engine (msiexec) uses the database to perform standard and custom actions for an operation (install, repair, uninstall, etc) on a product. Actions can set, pass and retrieve data via Windows Installer properties. A property is usually referenced via its name in square brackets, e.g., [VS2015]. Except for WiX-provided custom action (they you might or might not use), everything that is happens at install-time is Windows Installer.
WiX variables are simply a way of avoiding repetition in your WiX source. They are "compiled away" when WiX builds the package. So, their values are fixed. WiX's conditional compilation (define, if, etc) are also compiled away at build-time.
In your code, it seems you expect to use a property value in a conditional compilation statement. Property values are not set until msiexec runs. So, you have find another way of using the information you are gathering with registry search. One way might be, if you have a Feature that supports VS2015 and another that supports 2013, is to enable or disable features based on expressions that reference the property values.

If you want to detect which versions of Visual Studio are installed then look at the WiX-supplied WixVSExtension and just use the properties it supplies.
http://wixtoolset.org/documentation/manual/v3/customactions/wixvsextension.html
and it does include VS 2013 and 2015.

Related

WiX Change product name conditionally

I have a large .wxs file and a requirement to change the Product Name from MyApp Workstation version to MyApp Server version when the installer is launched on a Windows Server operating system. I read a lot and I found out that I need to relate to the following MSI property MsiNTProductType which returns the value 1 for workstation and 2 or 3 for server operating systems.
<?xml version="1.0" encoding="UTF-8"?>
<?define ProductName = "MyApp Workstation version" ?>
<Wix>
<Product Name="$(var.ProductName)" ... >
...
</Product>
</Wix>
If I use a condition like the following, it detects that I am on a workstation operating system (in my case Windows 10), but this is not what I want:
<Condition Message="This installer is for Windows Server only!">
<![CDATA[(MsiNTProductType > 1)]]>
</Condition>
I tried the preprocessor variable approach, but evidently it does not work:
<?if MsiNTProductType = 1 ?>
<?define ProductName = "MyApp Workstation version" ?>
<?else ?>
<?define ProductName = "MyApp Server version" ?>
<?endif ?>
I also tried SetProperty and CustomAction without any luck. I am stuck at this.
Is it possible to do something like this? What changes do I have to make to accomplish this? I am very new to WIX and I do not understand how it is supposed to work. Thank you.
LATER EDIT AND SOLUTION
After many days of trying tens of combinations, I was able to do this with the following code which I put before any CustomActions that were already defined:
<Property Id="ConditionalProductName" Value="MyApp Workstation version" />
<SetProperty Id="ConditionalProductName" Before="LaunchConditions" Value="MyApp Server version" >
<![CDATA[(MsiNTProductType > 1)]]>
</SetProperty>
<SetProperty Id ="ProductName" Before ="LaunchConditions" Value ="[ConditionalProductName]"/>
I hope this may help others too. Good luck.
The ProductName property can only be changed prior to the installation starting. Once MSI is running it's immutable.
The preprocessor statements you are trying effect build time not installation time.
The only way to do what you want is create a transform with the different name and then use a bootstrapper to install the MSI without a transform on a non server OS and install the MSI with a transform on a server OS.
Personally this isn't typical practice so I would push back on the requirement from the PM. The only reason I would go through the effort would be the business really really differentiated the branding on the marketing side. Otherwise this just isn't normally done.

Is it possible to pass a Wix variable to SuppressOptionsUI?

I am trying to get the Options button on the WixStandardBootstrapperApplication to be hidden if the application has already been installed.
I was hoping to be able to pass a variable to SuppressOptionsUI. But it seems the value of SuppressOptionsUI must be a literal yes or no.
This was the code I was using.
<!-- Don't show options button if we have an existing install -->
<Variable Name="suppressOptions" Type="string" Value="no"/>
<util:DirectorySearch
After='PreviousInstallFolderSearch'
Condition='PreviousInstallFolder'
Path='[PreviousInstallFolder]'
Result="exists"
Variable="suppressOptions"/>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkSidebarLicense">
<bal:WixStandardBootstrapperApplication
ShowVersion="yes"
LicenseUrl="http://static.my-site.com/EULA.html"
LogoFile="Installer-Banner.bmp"
LogoSideFile="Installer-FirstPage.bmp"
SuppressOptionsUI="[suppressOptions]"
/>
</BootstrapperApplicationRef>
So my question is: Is there another way of configuring the WixStandardBootstrapperApplication to allow SuppressOptionsUI to be configurable based upon a variable populated from a registry or directory search?
NB I am using the WixToolset only. No VBA or other MS tools.
"Not todayâ„¢"
This is an open issue, available for the taking: WixVariable to SuppressOptionsUI.

Wix "Product element contains an unexpected child element util: RegistrySearch" error message on launch condition

I am totally new to Wix and I have been tasked with this.
The installer should prompt the message "Application requires Reportviewer". It should check if reportViewer is installed and if not throw the message at the beginning of installation itself.
This is what I am trying to do (randomly trying things out as I still do not understand the details)
<Condition Message="This application requires ReportViewer.">
<![CDATA[ReportViewerV10 OR ReportViewerWow64V10]]>
</Condition>
<util:RegistrySearch
Root="HKLM"
Key="SOFTWARE\Microsoft\ReportViewer\v10.0"
Value="Install"
Variable="ReportViewerV10"
Win64="yes"
/>
<util:RegistrySearch
Root="HKLM"
Key="SOFTWARE\Wow6432Node\Microsoft\ReportViewer\v10.0"
Value="Install"
Variable="ReportViewerWow64V10"
Win64="yes"
/>
You need to add a reference to http://schemas.microsoft.com/wix/UtilExtension in your main container tag in WIX project to refer util:RegistrySearch.
Document Should Look Like
<?xml version="1.0"?>
<Include xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
.
.
.
</Include>
OR
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
.
.
.
</Wix>
You can keep this utility call in a Bundle tag or a Fragment tag only.
Refer RegistrySearch Element (Util Extension) Documentation for more details on this.
Refer WIX Documenation for more ideas.

How to decouple things in Wix?

I want to install a product with some dll with Wix 3.5.
These dll are determined during the msi installation through a radio buttons group.
I have :
a (fragment) wxs for myDllv1
a (fragment) wxs for myDllv2
a (UI fragment) wxs with the RadioButtonGroup to choose between myDll v1 and myDll v2 with a property INSTALLTYPE
a main wxs file which installs the correct version of myDll.
Problem : I have another set of dll to add and I want to modify as less files as possible.
I don't want to introduce bugs and I want to keep things decoupled.
I would like to modify only the UI fragment with the radio buttons and add a myDllv3 fragment (without doing any changes to my main wxs file, so no condition in that file..).
Is it possible?
Why don't you use pre-processors to select the correct fragments when building the msi?
<?if $(env.SomeBuildParameter) = SetA ?>
<?include myDllSetAv1.wxs ?>
<?include myDllSetAv2.wxs ?>
<?else ?>
<?include myDllSetBv1.wxs ?>
<?include myDllSetBv2.wxs ?>
<?endif ?>
I may be misunderstanding the question, but it sounds like your different set of Dlls should be grouped by features within WIX. I'd suggest creating independent WIX fragments that represents a feature for each of your set of Dlls and then you can tie your UI to install a specific feature as appropriate.
You represent a feature at the product level like so:
<Feature Id="Feature.One" Title="Feature One">
<ComponentGroupRef Id="FeatureOneDlls.Group" />
</Feature>
<Feature Id="Feature.Two" Title="Feature Two">
<ComponentGroupRef Id="FeatureTwoDlls.Group" />
</Feature>
And within each of the features I'd recommend using a separate wxs file to supply the fragment information that contains the files for that feature.

WiX: Prevent 32-bit installer from running on 64-bit Windows

Due to user confusion, our app requires separate installers for 32-bit and 64-bit versions of Windows. While the 32-bit installer runs fine on win64, it has the potential to create support headaches and we would like to prevent this from happening.
I want to prevent the 32-bit MSI installer from running on 64-bit Windows machines. To that end I have the following condition:
<Condition Message="You are attempting to run the 32-bit installer on a 64-bit version of Windows.">
<![CDATA[Msix64 AND (NOT Win64)]]>
</Condition>
With the Win64 defined like this:
<?if $(var.Platform) = "x64"?>
<?define PlatformString = "64-bit"?>
<?define Win64 ?>
<?else?>
<?define PlatformString = "32-bit"?>
<?endif?>
Thing is, I can't get this check to work right. Either it fires all the time, or none of the time. The goal is to check presence of the run-time msix64 variable against the compile-time Win64 variable and throw an error if these don't line up, but the logic is not working how I intend it to. Has anyone come up with a better solution?
Include the Condition element only in your 32-bit package (i.e., using ?if? preprocessor statement). The Condition would be "NOT Msix64": Launch conditions are things that must be true, so if Msix64 is set, the launch condition would fail and that means it's an x64 OS and a 32-bit package and the correct thing to do is to block.
We use the following...
<?if $(var.ProcessorArchitecture)=x86 ?>
<Condition Message="!(loc.LaunchCondition_Error64)">
<![CDATA[Installed OR Not VersionNT64]]>
</Condition>
<?endif?>
The condition element works with windows installer properties, which exist during an installation.
However, you are defining a Win64 as a wix variable, not a windows installer property. Wix variables only exist while the setup is created. You have to reference them as $(var.MyWixVariable) where you use them, and the wix preprocessor will then replace them with their defined value.
I would try this instead:
<?if $(var.Platform) = "x64"?>
<?define PlatformString = "64-bit"?>
<Property Id="Win64" Value="1" />
<?else?>
<?define PlatformString = "32-bit"?>
<?endif?>
If $(var.Platform) has the right value when the setup is created, then this will cause a "Win64" property to be recorded in the windows installer database (i.e. the MSI file) and the property will be available during installation for use in a condition element.
Add this condition
<Condition Message="This is designed for 32bit OS">%PROCESSOR_ARCHITECTURE ~= "x86" AND %PROCESSOR_ARCHITEW6432 <> "amd64"></Condition>
You could create one installer with a 32bit component and a 64bit component and put these two conditions in the respective components
<Component Id="bit32Component" Guid="..." Feature="ProductFeature">
<Condition>%PROCESSOR_ARCHITECTURE~="x86" AND %PROCESSOR_ARCHITEW6432<>"amd64"></Condition>
</Component>
<Component Id="bit64Component" Guid="..." Feature="ProductFeature">
<Condition>%PROCESSOR_ARCHITECTURE~="amd64" OR %PROCESSOR_ARCHITEW6432~="amd64"></Condition>
</Component>
here is a reference I used
http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx