I am trying to run a custom action at the end of my Wix installer but only if certain conditions are met. The user runs through the installer and they will choose one of two modes that set the property 'ServiceType'. The two values for the property are "RegisterNew" and "LinkExisting". You can see by the log below that when the user selects "LinkExisting" in the UI that it changes the property but the custom action still runs.
MSI (c) (D4:44) [11:20:15:686]: PROPERTY CHANGE: Modifying ServiceType property. Its current value is 'RegisterNew'. Its new value: 'LinkExisting'.
Here is my custom action code:
<InstallExecuteSequence>
<Custom Action="RegisterServiceNameCustomAction" Before="InstallFinalize">
<![CDATA[(ServiceType="RegisterNew") AND (NOT Installed)]]>
</Custom>
</InstallExecuteSequence>
<Fragment>
<Binary Id="RegisterServiceCustomActionBinary" SourceFile="$(var.RegisterServiceCustomAction.TargetDir)$(var.RegisterServiceCustomAction.TargetName).CA.dll" />
<CustomAction Id="RegisterServiceNameCustomAction" BinaryKey="RegisterServiceCustomActionBinary" DllEntry="ShowRegisterService" Execute="deferred" Return="check" />
</Fragment>
Here are the different conditions I have tried:
(ServiceType="RegisterNew") AND (NOT Installed)
<![CDATA[(ServiceType="RegisterNew") AND (NOT Installed)]]>
ServiceType="RegisterNew" AND NOT Installed
Here is the code for my custom Dialog where they are selecting making their selection that will change "ServiceType":
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="SelectServiceDlg">
<Property Id="ServiceType" Value="RegisterNew" />
<Dialog Id="SelectServiceDlg" Width="370" Height="270" Title="[ProductName] [Setup]" NoMinimize="yes">
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[DialogBitmap]" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="40" Transparent="yes" NoPrefix="yes" Text="Determine whether you need to register a new service or link an existing service." />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="Service Type Selection" />
<Control Id="BothScopes" Type="RadioButtonGroup" X="20" Y="55" Width="330" Height="120" Property="ServiceType">
<RadioButtonGroup Property="ServiceType">
<RadioButton Value="RegisterNew" X="0" Y="0" Width="295" Height="16" Text="Register New Service" />
<RadioButton Value="LinkExisting" X="0" Y="60" Width="295" Height="16" Text="Link Existing Service" />
</RadioButtonGroup>
</Control>
<Control Id="RegisterNewServiceDescription" Type="Text" X="33" Y="70" Width="300" Height="36" NoPrefix="yes" Text="Select this option if you are going to register a new service.">
</Control>
<Control Id="LinkExistingDescription" Type="Text" X="33" Y="130" Width="300" Height="36" NoPrefix="yes" Text="Select this option if you are going to link an existing service to this service.">
</Control>
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>
Here is an image of the UI:
So my question is why is it executing the custom action even though my condition is specifically checking that property?
After some reading of documentation and looking at all of the "properties" of the tag in WIX I decided to try and set a couple of other values and see what happened. I found that when defining the Property if you mark it as secure it then retains its value throughout the entire install process whereas if it is not secure it does not seem to do that. So now my property definition looks like this:
<Property Id="SERVICE_TYPE" Secure="yes" Value="RegisterNew" />
You'll notice that I had to change the name to call caps because when you mark a property as a secure property then you can not have any lowercase letters in the name.
Here is a snippet from the WIX documentation:
Secure -- YesNoType -- Denotes that the property can be passed to the server-side when doing a managed installation with elevated privileges. See the SecureCustomProperties Property for more information.
WIX Documentation For Property Element
Related
I am fairly new to WiX and I got an issue where I cannot read a value from the registry to a Checkbox. I can read and populate to a ComboBox properly from the registry but for some reason the checkbox is not working.
Here is a part of my CustomUI.wxs
<Property Id="HEAPSIZEVALUE" Value="-Xms1024m" Secure="yes">
<RegistrySearch Id="RegHeapSizeValue" Type="raw" Root="HKCU"
Key="Software\Altair Semiconductor\!(loc.ProductName)" Name="Heap_Size" />
</Property>
<Property Id="POWERMODE" Value="1" Secure="yes">
<RegistrySearch Id="RegPowerModeValue" Type="raw" Root="HKCU"
Key="Software\Altair Semiconductor\!(loc.ProductName)" Name="Power" />
</Property>
<SetProperty Id="POWERMODE" Value="0" Before="InstallInitialize" Sequence="execute">NOT POWERMODE</SetProperty>
<UI Id="WixUI_MyMondo">
<Dialog Id="UserOptionsDialog" Width="370" Height="270" Title="Dialog Title">
<Control Id="TextLine2" Type="Text" X="50" Y="30" Width="250" Height="55" Text="Please choose the values for each of the following options (This can be skipped if typical options suffice)" TabSkip="yes" Transparent="yes" />
<Control Id="heapSizeLabel" Type="Text" X="50" Y="80" Height="17" Width="55" Transparent="yes" Text="Heap Size:" />
<Control Id="ComboBoxMain" Type="ComboBox" X="100" Y="79" Width="150" Height="20" Property="HEAPSIZEVALUE" >
<ComboBox Property="HEAPSIZEVALUE">
<ListItem Value="-Xms1024m" />
<ListItem Value="-Xms2048m" />
<ListItem Value="-Xms4096m" />
</ComboBox>
</Control>
<Control Id="PowerMode" Type="CheckBox" X="50" Y="100"
Width="290" Height="17" Property="POWERMODE"
CheckBoxValue="[POWERMODE]"
Text="Power (Allow device to sleep)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="Back" />
</Dialog>
Here is my registry
My installer
As you can see my Heap_size field is read properly from the registry and shown to the user but for some reason the checbox is always shown as selected.
I went through the logs also and I see that the value is read properly from the registry
MSI (c) (08:24) [11:28:01:194]: PROPERTY CHANGE: Modifying POWERMODE property. Its current value is '1'. Its new value: '0'.
In Windows Installer, the CheckBoxValue field is the value of the property when the checkbox is selected not the property itself. When it's not selected it's null. So change it to CheckBoxValue="1".
Where it says Property="POWERMODE" this is the property that will control the checkbox. If it matches the value of CheckBoxValue then it'll be checked. If it's null it won't.
There is a wierd UI bug (feature?) in MSI that if you don't give CheckBoxValue a value then the control can't be checked and unchecked.
https://learn.microsoft.com/en-us/windows/win32/msi/checkbox-table
Remarks
If the check box is selected, then the corresponding property is set
to the specified value. If there is no value specified or this table
does not exist, then the property is set to its original value when
the check box is selected. If the original value is null, the property
is set to "1".
By the above logic an unspecified value causes the uncheck to set the property to 1 which then gets interpreted as checked causing the deadlock.
New to WIX here :-)
I added a new dialog to my WIX setup project, and it works well, except that this dialog ONLY shows the controls I added to it - it doesn't have the next/back/cancel buttons or the banner that the other dialogs have.
Did I do something wrong or do I have to manually recreate all controls, inclulding banners? If I have to manually recreate them, where do I find the WXS files that contains the originals?
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<RadioButtonGroup Property="MyApp_Database_Type">
<RadioButton Height="17" Text="Dedicated" Value="Dedicated" Width="348" X="0"
Y="0" />
<RadioButton Height="17" Text="Shared" Value="Shared" Width="348" X="0"
Y="18" />
<RadioButton Height="17" Text="Single User" Value="Single User" Width="348" X="0"
Y="36" />
</RadioButtonGroup>
<Dialog Id="MyApp_UI_DatabaseProperties" X="50" Y="50" Width="373" Height="287"
Title="[ProductName]: Database Properties">
<Control Id="CTL_MyApp_UI_DatabaseProperties" Type="RadioButtonGroup" X="18" Y="108" Width="348" Height="48"
Property="MyApp_Database_Type" Text="System Type" TabSkip="no" />
<Control Id="Back" Type="PushButton" X="156" Y="243"
Width="56" Height="17" Hidden="no" Disabled="no" Text="Back" />
<Control Id="Next" Type="PushButton"
X="212" Y="243" Width="80" Height="17" Default="yes"
Text="Next" Hidden="no" Disabled="no">
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>
Yes you have to fully define the dialog you want to use. Each dialog is a self contained and describing thing. It doesn't know about the layout or format of any other dialogs in the installation.
You can see examples of the dialogs you are probably using with the WixUIExtension.dll right here. This is the source code of the UIExtension's wixlib.
You should be able to simply copy over the shared components from the other dialogs into the one you are describing to get it working as you expect.
I am trying to make changes to the Windows firewall based on a property that is set in a dialog. I can see in the log that the property is being set correctly but the firewall rules are being created regardless of the value of the property.
My code is...
<Component Id="ChangeFirewall" Guid="*" KeyPath="yes">
<Condition><![CDATA[ChgFirewall = "True"]]></Condition>
<fire:FirewallException Id="FW6501" Name="6501" Port="6501"
Protocol="tcp" Scope="any"/>
<fire:FirewallException Id="FW6502" Name="6502" Port="6502"
Protocol="tcp" Scope="any"/>
<fire:FirewallException Id="FW6505" Name="6505" Port="6505"
Protocol="tcp" Scope="any"/>
</Component>
If ChgFirewall is False why does the firewall get changed?
Update: I have added the code for the dialog that sets the CHGFIREWALL property...
<Dialog Id="FirewallDlg" Width="370" Height="270" Title="[ProductName] Setup" NoMinimize="yes">
<Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="40" Transparent="yes" NoPrefix="yes">
<Text>This program uses TCP ports 6501, 6501, and 6505 for coordinating information between workstations. These ports must be unblocked for it to work correctly</Text>
</Control>
<Control Id="Instructions" Type="Text" X="20" Y="70" Width="280" Height="30" Transparent="yes" NoPrefix="yes">
<Text>This installer can attempt to automatically modify the Windows Firewall for you, or you may manually modify the firewall settings.</Text>
</Control>
<Control Type="RadioButtonGroup" Property="CHGFIREWALL" Id="CHGFIREWALL" Width="340" Height="44" X="20" Y="120">
<RadioButtonGroup Property="CHGFIREWALL">
<RadioButton Text="Have the installer update the firewwall settings for Guru (Recommended)" Height="13" Value="True" Width="340" X="0" Y="0" />
<RadioButton Text="Manually update the firewall settings" Height="13" Value="False" Width="340" X="0" Y="15" />
</RadioButtonGroup>
</Control>
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next">
<Publish Event="EndDialog" Value="Return"></Publish>
</Control>
<Control Id="CancelButton" Type="PushButton" Text="Cancel" Height="17" Width="56" X="180" Y="243" Cancel="yes">
<Publish Event="EndDialog" Value="Exit" />
</Control>
</Dialog>
Also this is my definition of the property...
<Property Id='CHGFIREWALL' Value='False' Secure='yes'/>
As a first step, UPPERCASE the property and set the attribute 'secure="yes". This ensures that the property is passed properly to the server process as explained in the comments here.
Then the issue is how you set the property? Is is set by a custom action, or do you set it in the Property table or on the command line?
In my installer I want user to connect to database. I support 4 database types in my product.
In the connect to database dialog I created, there is a ComboBox control with all supported database types, Edit control where user suppose to enter the connection string and a PushButton, when pressed it will show connection string text template in Edit control according to selected database type in ComboBox. Now, the problem is:
User clicks Show Template button when MSSQL is selected
User alters manually place holder in text template connection string in Edit
control
User realize that he needs MySQL connection
User change value in ComboBox to MySQL and clicks Show Template button and nothing
happens.
To summarize this, after Edit control were manually altered, the Show Template stops working.
Here is WiX code use:
<Fragment>
<!-- Supported databases templates -->
<Property Id="MSSQLTemplate" Value="Data Source=localhost;Initial Catalog=[database];Integrated Security=yes"/>
<Property Id="MySQLTemplate" Value="Server=localhost;Uid=[username];Pwd=[password];Database=[database];" />
<Property Id="DB2Template" Value="Server=localhost;Uid=[username];Pwd=[password];Database=[database];" />
<Property Id="OracleTemplate" Value="Data Source=[database];User Id=[username];Password=[password];" />
<Property Id="PROP_DATABASE_TYPE">MSSQL</Property>
<Property Id="PROP_CONNECTIONSTRING"></Property>
<Binary Id="CA_DLL" SourceFile="$(var.CustomActions.TargetDir)CustomActions.CA.dll" />
<CustomAction Id="caShowTemplate" BinaryKey="CA_DLL" DllEntry="ShowTemplate" Execute="immediate" />
<UI Id="InstallDlg_UI">
<TextStyle Id="Tahoma_Regular" FaceName="Tahoma" Size="8" />
<Property Id="DefaultUIFont" Value="Tahoma_Regular" />
<Dialog Id="InstallDlg" Width="370" Height="270" Title="Amazing Software" NoMinimize="no">
<!-- Database type -->
<Control Id="lblDatabaseType" Type="Text" X="20" Width="100" Y="60" Height="18" NoPrefix="yes" Text="Database Type" />
<Control Id="cbDatabaseServer" Type="ComboBox" X="120" Width="90" Y="60" Height="18" Property="PROP_DATABASE_TYPE" ComboList="yes" Sorted="yes">
<ComboBox Property="PROP_DATABASE_TYPE">
<ListItem Text="MSSQL" Value="MSSQL" />
<ListItem Text="MySQL" Value="MySQL" />
<ListItem Text="Oracle" Value="Oracle" />
<ListItem Text="DB2" Value="DB2" />
</ComboBox>
</Control>
<Control Id="btnShowTemplate" Type="PushButton" X="215" Y="60" Width="85" Height="17" Text="Show Template">
<Publish Event="DoAction" Value="caShowTemplate" Order="1">1</Publish>
<Publish Property="PROP_CONNECTIONSTRING" Value="[PROP_CONNECTIONSTRING]" Order="2">1</Publish>
</Control>
<!-- Connection string -->
<Control Id="lblConnectionString" Type="Text" X="20" Width="100" Y="85" Height="18" NoPrefix="yes" Text="Connection String" />
<Control Id="tbConnectionString" Type="Edit" X="120" Width="180" Y="85" Height="18" Property="PROP_CONNECTIONSTRING" Text="[PROP_CONNECTIONSTRING]" />
<Control Id="CancelButton" Type="PushButton" Text="Cancel" Height="17" Width="56" X="180" Y="243" Cancel="yes">
<Publish Event="EndDialog" Value="Exit" />
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="InstallDlg" Before="ExecuteAction" />
</InstallUISequence>
</UI>
</Fragment>
And a custom action written in C#:
[CustomAction]
public static ActionResult ShowTemplate(Session session)
{
string selectedDatabase = string.Format("{0}Template", session["PROP_DATABASE_TYPE"]);
session["PROP_CONNECTIONSTRING"] = session[selectedDatabase];
return ActionResult.Success;
}
What am I doing wrong?
Your code doesn’t have any issue. It is a well-known limitation of WIX UI. Check the below discussions for more details.
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/UI-Edit-Box-not-updating-td5077648.html
Wix Interactions with Conditions, Properties & Custom Actions
I'm facing an issue with my WiX installer.
I have a custom dialog that contains an edit control linked to a property. At runtime, if I change the value in the edit control, I see from the log that the property is properly updated with that new value. But it seems that, when the InstallUISequence ends, the property is reset to its default value, which is annoying, because I cannot use the user sumitted value in a custom action part of the InstallExecuteSequence.
Here is an extract of the WXS script I use:
<UI>
<Dialog Id="select_list" Width="370" Height="270" Title="Select license and list files">
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="UIBannerBmp" />
<Control Id="BannerLine" Type="Line" X="0" Y="45" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Type="Edit" Id="list" Width="211" Height="15" X="128" Y="128" Property="pListFile" />
<Control Type="Text" Id="static_list" Width="78" Height="17" X="41" Y="154" Text="list file" />
<Control Type="PushButton" Id="next" Width="50" Height="17" X="232" Y="244" Text="Next >">
<Publish Event="EndDialog" Value="Return">1</Publish>
</Control>
<Control Type="PushButton" Id="cancel" Width="50" Height="17" X="296" Y="244" Text="Cancel">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Type="Text" Id="desc" Width="348" Height="16" X="8" Y="90"
Text="Please set the path of the the list file" />
</Dialog>
<InstallUISequence>
<Show Dialog="select_list" After="WelcomeEulaDlg">NOT installed</Show>
</InstallUISequence>
</UI>
<CustomAction Id="InstallService"
ExeCommand="[bin]prog.exe -f install.cl '[pListFile]'"
Execute="immediate"
Return="check"
Directory="bin" />
<InstallExecuteSequence>
<Custom Action="InstallService" After="InstallFinalize">REMOVE=""</Custom>
</InstallExecuteSequence>
<CustomActionRef Id="InstallService" />
<Property Id="pListFile" Value="c:\" />
I must not be on the right track to exchange information between the two sequences.
Is there a way to do that?
You need to mark the Property "Secure" for it to pass from the client-side (InstallUISequence) to server-side (InstallExecuteSequence). To do that you need to make the Property "public" (ALL CAPS) and secure. Something like so:
<Property Id="PLISTFILE" Secure="yes"/>
You don't need to give it a value unless you want something to show up by in your UI by default.