WIX Property as Integer - wix

I am trying to set a a property to configure the IIS:Website ConnectionTimeout value on a new website that gets created during setup.
However I am unable to, as the value for ConnectionTimeout must be an integer, not string.
In my product.wxs I have the following:
<Control Id="IisConnectionTimeoutLabel" Type="Text" X="45" Y="164" Width="100" Height="15" TabSkip="no" Text="Connection Timeout (sec):" />
<Control Id="IisConnectionTimeoutEdit" Type="Edit" X="45" Y="176" Width="220" Height="18" Property="IIS_CONNECTIONTIMEOUT" Text="{80}" Integer="yes" />
And in my IisConfiguration.wxs I have the following:
<Property Id="IIS_CONNECTIONTIMEOUT" Value="300" />
<iis:WebSite Id="EersWebsite" Description="[IIS_WEBSITENAME]" ConfigureIfExists="yes" Directory="WEBINSTALLDIR" DirProperties="EersWebsiteDirProperties" ConnectionTimeout="[IIS_CONNECTIONTIMEOUT]">
When I build the project I get the following:
The 'ConnectionTimeout' attribute is invalid - The value
'[IIS_CONNECTIONTIMEOUT]' is invalid according to its datatype
'http://www.w3.org/2001/XMLSchema:nonNegativeInteger' - The string
'[IIS_CONNECTIONTIMEOUT]' is not a valid Integer value.
The iis:WebSite/#ConnectionTimeout attribute's value,
'[IIS_CONNECTIONTIMEOUT]', is not a legal integer value. Legal
integer values are from -2,147,483,648 to 2,147,483,647.
Thanks in advance

As the error message states, the value of the <iis:WebSite>'s ConnectionTimeout attribute expects the integer value. The nonNegativeInteger is not a Formatted type, which knows how to extract values out of properties provided in square brackets.
Hence, I don't think you have a way here apart from providing the hard-coded value...
Alternatively, you can create a custom action, which calls for appcmd.exe, and provide the required timeout value in the command-line, and schedule this action deferred after ConfitureIIs... But the efforts seem much bigger than the benefit...

Related

WIX: Setting a registry value from a dialog checkbox

Using Wix for the first time in 10+ years, and first time with forms/dialog entry.
Have a property defined more or less like this:
<Property Id="THE_FLAG">
<RegistrySearch Id="SearchTheFlag" Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.SimpleProductName)" Name="the_flag" Win64="$(var.Win64)" Type="raw" />
</Property>
Have a control in a form to set it:
<Control Id="TheFlagCheckBox" Type="CheckBox" X="45" Y="80" Width="220" Height="17" Property="THE_FLAG" CheckBoxValue="1" Text="Flag for something" />
At the end I want to write it:
<RegistryKey Root='HKLM' Key='SOFTWARE\$(var.Manufacturer)\$(var.SimpleProductName)' ForceCreateOnInstall='yes' >
<RegistryValue Name='the_flag' Type ='integer' Value='[THE_FLAG]' />
</RegistryKey>
If I select the checkbox, it sets the registry value. However, if I don't check the checkbox, then I get a warning when running the installer about not being able to acces the registry value. I think it is because the "value" of "THE_FLAG" is null or the empty string. I want to avoid the nasty warning to the user. I took over some code, and the previous owner used all strings for obviously DWORD values...maybe to get around the warning.
Can I set some conditionals or set the value of THE_FLAG to "0" if it is "" or null?
Add the following to your authoring:
<SetProperty Id="THE_FLAG" Value="0" Before="InstallInitialize" Sequence="execute">NOT THE_FLAG</SetProperty>
This will set the value of THE_FLAG to "0" if it's blank (in MSI, null and empty string are both blank) before the registry writes are done. A reasonable alternate value for Before is "WriteRegistryValues".

WiX: how to expand the variable which is used in the localized string?

WiX.
This is my localized String:
<String Id="SelectInstallDir_WARNING_Text">Don't select the "$(env.ProgramData)\Autodesk\ApplicationPlugins\ProxyTools.bundle\" variant if you will use AutoCAD 2012, because its bundle-autoloader don't monitor of that directory.</String>
I use that string here:
<Control Id="warning_acad2012_text" Type="Text" X="10" Y="170" Width="350" Height="60"
Transparent="yes" NoPrefix="yes">
<Text>{\DlgFont10_important}!(loc.SelectInstallDir_WARNING_Text)</Text>
</Control>
But I see that $(env.ProgramData) variable wasn't expanded.
How can I fix it?
Assuming you want the current value at install time, instead of the value from the build machine, you should Windows Installer's formatting. Specifically you should reference a directory property such as "... [CommonAppDataFolder] ..." or an environment variable such as "... [%ProgramData] ...".

WiX Toolset - Hidden property no longer hidden when referenced elsewhere

To hide a property in WiX I'm using
<Property Id="MY_PASSWORD" Hidden="yes" />
Or
<Control Id="Password" Password="yes" Type="Edit" X="30" Y="173" Width="220" Height="18" Property="MY_PASSWORD">
What I haven't found a reliable solution for is how to keep a previously hidden password hidden in a log file after it's been evaluated in:
Another property (e.g. SetProperty, type 51 CustomAction, publish property ina dialog)
A util:XmlFile entry
Is there a way to have a password evaluated without exposing the password once it's used in another WiX element?
In the instances of SetProperty or a type 51 CustomAction, is there a way to hide the original password without needed to hide the rest of the string.
For example set Property="SOME_STRING" Value="password=[MY_PASSWORD];other=[ANOTHER_PROPERTY]", have the property string show up as "password=********;other=the evaluated string"
In the instance of using util:XmlFile, is there any way to hide a password that's evaluated here from showing up in a log file?
This is the solution I came up with, I'm open to better solutions.
In the case of (e.g. SetProperty, type 51 CustomAction, or publish property in a dialog), what I did is create a reference to the property, which I mark as Hidden="yes".
<Property Id="Property_2" Hidden="yes" />
To handle the case: For example set Property="SOME_STRING" Value="password=[MY_PASSWORD];other=[ANOTHER_PROPERTY]", have the property string show up as "password=********;other=the evaluated string"
What I did was write a type 51 CustomAction to create that new property
<CustomAction Id="Set.NewProperty" Property="NewProperty" Value="password=[MY_PASSWORD];other=[ANOTHER_PROPERTY]" />
And add a separate reference to the new property to hide it.
<Property Id="NewProperty" Hidden="yes" />
This worked for me to obscure these details from util:XmlFile.
This solution, in my opinion is less than perfect. Using this method hides the entire string. I would prefer a solution that only hides the password details portion of the string.

Checking port value using CDATA in WiX

I want to have a port number validation in my WiX installer. Using one of codes below, I try to check if a database port has a value between 1024 and 65535:
1. <Publish Event="SpawnDialog" Value="InvalidPortNumber"><![CDATA[(DATABASE_PORT < 1024 OR DATABASE_PORT > 65535)]]></Publish>
2. <Publish Event="SpawnDialog" Value="InvalidPortNumber"><![CDATA[(DATABASE_PORT < "1024" OR DATABASE_PORT > "65535")]]></Publish>
But none of them do not publish a spawn dialog if the user writes a port number less than 1024. For value greater than 65535 everything works good.
The port number is set in:
<Control Id="DatabasePortText" Type="MaskedEdit" X="20" Y="120" Width="50" Height="15" Property="DATABASE_PORT" Text="######"/>
How can I fix this problem?
The problem is that your property is treated as string, thus < and > don't really make sense in the way that it should.
You have two choices:
Use Edit control and set Integer attribute as yes: <Control Type="Edit" Integer="yes" .../>. This will make sure that property is treated as integer.
Use MaskedEdit, and when you press Next button, a custom action will be executed which can convert string property into integer property.

How to inspect a CustomAction's property (Wix)?

I am trying to put together a small 'prerequisites' dialog in Wix to give confidence to the users that they have all of the required things needed to run my software:
For example, I have a need for Managed DirectX, so I look for some DLLs:
<Property Id="MANAGED_DIRECTX">
<DirectorySearch Path="$(env.SystemRoot)\Microsoft.NET\DirectX for Managed Code\1.0.2902.0" Depth="0" Id="MDXDir">
<FileSearch Name="Microsoft.DirectX.dll"/>
</DirectorySearch>
</Property>
<Property Id="MANAGED_DIRECTX_DIRECTINPUT">
<DirectorySearch Path="$(env.SystemRoot)\Microsoft.NET\DirectX for Managed Code\1.0.2902.0" Depth="0" Id="MDXInputDir">
<FileSearch Name="Microsoft.DirectX.DirectInput.dll"/>
</DirectorySearch>
</Property>
I also have a CustomAction to combine my condition logic:
<CustomAction Id="SetManagedDirectXInstalled"
Property="MANAGED_DIRECTX_INSTALLED"
Value="NOT([MANAGED_DIRECTX] = '') AND NOT ([MANAGED_DIRECTX_DIRECTINPUT] = ''")/>
This CustomAction is sequenced:
<InstallExecuteSequence>
<Custom Action="SetManagedDirectXInstalled" After="AppSearch" />
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
What I should now be able to do is use "MANAGED DIRECTX INSTALLED" to do something, e.g.
<Control Id="NoManagedDirectX" Type="Text" X="20" Y="50" Width="300" Height="60" Transparent="yes" NoPrefix="yes" Hidden="yes">
<Text>Microsoft Managed DirectX (MDX) for DirectX 9.0 is NOT installed</Text>
<Condition Action="show">NOT MANAGED_DIRECTX_INSTALLED</Condition>
</Control>
<Control Id="ManagedDirectX" Type="Text" X="20" Y="50" Width="300" Height="60" Transparent="yes" NoPrefix="yes" Hidden="yes">
<Text>Microsoft Managed DirectX (MDX) for DirectX 9.0 is correctly installed</Text>
<Condition Action="show">MANAGED_DIRECTX_INSTALLED</Condition>
</Control>
It doesn't matter what I do, the condition is always false (e.g. not installed) even when I know the files are there. Using the msiexec command with /l*vx does not show the MANAGED DIRECTX INSTALLED property anywhere.
When a <Condition> is used with the following, it successfully prevents installation (although I no longer want to block installs in this case, just advise).
<Condition Message="You must have Microsoft Managed DirectX (MDX) for DirectX 9.0 installed">
MANAGED_DIRECTX AND MANAGED_DIRECTX_DIRECTINPUT
</Condition>
How can I trace/debug this (or what have I done wrong?)
EDIT - I'm now certain that my CustomAction is not even being called, setting it to the following is not showing expected results either!
<CustomAction Id='SetManagedDirectXInstalled'
Property='MANAGED_DIRECTX_INSTALLED'
Value='Something hard-coded'/>
or
<CustomAction Id='SetManagedDirectXInstalled'
Error='Some error should show!'/>
I think I may have found the answer, but I can't try it until I'm next at my development PC.
It appears I have to compare the values to TRUE/FALSE (or empty string) not just expecting it to work as boolean (Source)
In these expressions, you can use
property names (remember that they are
case sensitive). Non-existent property
names will be treated as empty
strings. The logical value of a
property reflects whether it has been
set—meaning that you cannot check for
a logical value by simply using the
property:
PROPERTY
This will evaluate to true if the property has been set and has any
value, even if this value is false.
NOT PROPERTY
This will evaluate to true if the property has not been set at all.
PROPERTY = TRUE
PROPERTY = FALSE
This is the proper way to check the value of a logical property.
To debug, use a verbose log file. It will show you the states of your Properties as they change. You should then be able to evaluate the Condition with that knowledge
I answered this same question not too long ago here. A Condition that uses the Property name is a test for existence. An existence test for a Property evaluates to true if the Property has any value at all. If you want to check the value of a Property you need to do so explicitly.