The case is, I want to have a checkbox in a dialog. If the checkbox
is checked I want to create a file and do some other stuff.
I have a custom action which should using the value of the checkbox-property.
Now I try to pass the checkbox value to my CA-Method but it never receives a value,
the variable is present but always empty. I asume the checkbox variable itself
is not present at this point, because session.CustomActionData.ToString() shows:
INSTALLFOLDER=C:\Program Files (x86)\WixTesterSetup\;CHECKBOXProperty=
My Dialog is:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="UserRegDialogUI">
<Property Id="Proceed">proceedbtn</Property>
<Dialog Id="UserRegDialog" Width="400" Height="300" Title="Atled Service Konfiguration">
<Control Id="headerText" Type="Text" X="65" Y="10" Width="350" Height="40" Transparent="yes" Text="Something to Check" />
<Control Id="checkboxLabel" Type="Text" X="58" Y="150" Height="14" Width="141" Transparent="yes" Text="Checkbox Text" />
<Control Id="checkbox" Type="CheckBox" X="60" Y="165" Height="17" Width="120" Property="CHECKBOXProperty" CheckBoxValue="true" />
<Control Id="proceedButton" Type="PushButton" Text="Weiter" Height="20" Width="43" X="349" Y="266">
<Publish Event="EndDialog" Value="Return">1</Publish>
</Control>
<Control Id="cancelButton" Type="PushButton" Text="Beenden" Height="22" Width="50" X="293" Y="266" Cancel="yes">
<Publish Event="EndDialog" Value="Exit" />
</Control>
</Dialog>
</UI>
<InstallUISequence>
<Show Dialog="UserRegDialog" Before="ExecuteAction" />
</InstallUISequence>
</Fragment>
</Wix>
And Product.wsx contains:
<Binary Id="CustomActionBinary" SourceFile="$(var.RegistrationInfoCustomAction.TargetDir)$(var.RegistrationInfoCustomAction.TargetName).CA.dll"/>
<CustomAction Id="RegistrationInfoCustomAction" BinaryKey="CustomActionBinary" DllEntry="SaveUserInfo" Execute="deferred" Impersonate="no" />
<CustomAction Id="CustomAction51" Property="RegistrationInfoCustomAction" Value="INSTALLFOLDER=[INSTALLFOLDER];CHECKBOXProperty=[CHECKBOXProperty]" />
<InstallExecuteSequence>
<Custom Action="CustomAction51" Before='InstallFinalize' />
<Custom Action='RegistrationInfoCustomAction' After='CustomAction51'>NOT Installed</Custom>
</InstallExecuteSequence>
I tried to initialize set the property:
<Property Id="CHECKBOXProperty" Value="true" />
In that case it´s always true even if I uncheck the box.
I tried empty value (compiler says the property will be ignored)
May someone tell me a solution?
It looks like you're running your custom action with deferred context and I think this is what's causing your problems. Read through Obtaining Context Information for Deferred Execution Custom Actions. If you put your property in CustomActionData it should then be available.
Related
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
I would like to alter text in ExitDialog depending on result of an immediate action, executed after InstallFinalize. I have tried to do this with the use of property to be set by the action (ISSUCCEEDED in the snippet below), but as I understand it, installer lost this property after the transition from server to client phase. If so, how this could be done?
<!-- The MyAction sets the property ISSUCCEEDED -->
<CustomAction Id="MyAction" BinaryKey="..." DllEntry="..."/>
<InstallExecuteSequence>
<Custom Action="MyAction" After="InstallFinalize">...</Custom>
</InstallExecuteSequence>
<UI>
<Dialog Id="MyExitDialog" ...>
...
<!-- ISSUCCEEDED is lost by now -->
<Control Id="C1" Type="Text" Hidden="yes" Text="!(loc.Text1)"...>
<Condition Action="show">ISSUCCEEDED</Condition>
</Control>
<Control Id="C2" Type="Text" Hidden="yes" Text="!(loc.Text2)"...>
<Condition Action="show">NOT ISSUCCEEDED</Condition>
</Control>
...
</Dialog>
</UI>
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 am new to create MSI installer using wix tool,here i have a query please help me how to resolve this .
My query is : I have create a custom UI , in this i have a combo box control and i have bind the combo box values as dynamically using custom Action method it's working fine . Now, i want pass the parameters(combo box selected value) to custom action method,i don't know how to pass parameters .I goggled but i did not get answer please help me.
Here is my code
<Binary Id="CustomActions" SourceFile="D:\WIX Projects\ExampleSetup\CustomAction1\bin\Debug\CustomAction1.CA.dll" />
<CustomAction Id='Action1' BinaryKey='CustomActions' DllEntry='FillServerInstances' Execute='immediate' Return='check' />
<UI>
<Dialog Id="CustomWelcomeEulaDlg" Width="600" Height="450" Title="!(loc.WelcomeEulaDlg_Title)">
<Control Id="Bitmap" Type="Bitmap" X="0" Y="44" Width="600" Height="380" TabSkip="no" Text="MainImage" />
<Control Id="Next" Type="PushButton" X="290" Y="430" Width="60" Height="17" Default="yes" Text="Next">
<Publish Event="DoAction" Value="Action1">1</Publish>
<Publish Event="NewDialog" Value="LicenseAgreementDlgs"><![CDATA[1]]></Publish>
<Publish Event="ReinstallMode" Value="ecmus"><![CDATA[Installed = 1]]></Publish>
</Control>
<Control Id="Cancel" Type="PushButton" X="350" Y="430" Width="56" Height="17" Cancel="yes" Text="Cancel">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="Title" Type="Text" X="15" Y="6" Width="300" Height="15" Transparent="yes" NoPrefix="yes">
<Text>[DlgTitleFont]Welcome to the [ProductName] [Wizard]</Text>
</Control>
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="600" Height="0" />
</Dialog>
Latest Code
<Product Id="22d32870-651b-4eee-a622-27b2daaade8c" Name="Small Business" Language="1033" Version="1.0.0.0" Manufacturer="Small Business Manufacturing" UpgradeCode="01b2dc2f-61f3-4ff0-a0ba-94dd4cb0829d">
<Package InstallerVersion="200" Compressed="yes" />
<Property Id="MSIFASTINSTALL" Value="3" />
<Binary Id="BIN_CustomAction" SourceFile="D:\WIX Projects\ExampleSetup\CustomAction1\bin\Debug\CustomAction1.CA.dll"/>
<Binary Id="myAction" SourceFile="D:\WIX Projects\ExampleSetup\CustomAction1\bin\Debug\CustomAction1.CA.dll"/>
<UIRef Id="WixUI_CustomMinimal" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Property Id="FILEPATH" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="Small Business Manufacturing">
<Component Id="Component" Guid="af10d5b4-5d25-474f-8360-13b6c0cd7a53">
<File Id="Component" Source="D:\WIX Projects\Small Business Manufacturing\Small Business Manufacturing\bin\Debug\Myproject.exe" Compressed="yes" KeyPath="yes" Checksum="yes" />
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="Installation Target" Level="1">
<ComponentRef Id="Component" />
</Feature>
<InstallExecuteSequence>
<Custom Action="myActionId" After="InstallFinalize"></Custom>
</InstallExecuteSequence>
<CustomAction Id="SetCustomActionDataValue" Return="check" Property="myActionId" Value="AnotherValue=[Sqlinstaces]" />
<UI>
<ProgressText Action="RunEXE">Configuring Foo... (this may take a few minutes).</ProgressText>
</UI>
</Product>
As far as I am aware you can't pass parameters to custom actions. You can set a property in Wix and use WcaGetProperty to access that.
I use a listbox which is similar like so:
<!--This will be populated via the custom action-->
<Control Id="ListBoxID" Type="ListBox" Property="COMPORT" Width="80" Height="40" X="80" Y="165" Indirect="no">
<ListBox Property="COMPORT">
</ListBox>
</Control>
And in my C++ Custom Action:
hr = WcaGetFormattedProperty(L"COMPORT",&szComport);
ExitOnFailure(hr, "failed to get Com Port");
EDIT:
Ok so I am assuming your ComboBox is something like this:
<Control Id="DummyComboBox" Hidden="yes" Type="ComboBox" Sorted="yes" ComboList="yes" Property="DUMMYPROPERTY" X="65" Y="60" Width="150" Height="18">
<ComboBox Property="DUMMYPROPERTY">
</ComboBox>
Make sure your property is is defined like so(ensure capital letters):
<Property Id="DUMMYPROPERTY" Secure="yes"></Property>
You do not need a custom action to send the value of the property. All you have to do is use:
LPWSTR dummyText = NULL;
hr = WcaGetProperty(L"DUMMYPROPERTY", &dummyText);
ExitOnFailure(hr, "failed to get Dummy Text");
That is for a C++ Custom Action not sure what you are using but a quick google search would tell you the relevant code to use.
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.