WIX The properties modified in the custom action are not correct in the exit dialog - wix

I need to determine if the user has installed SQL during the installation phase, and if the user is not installed, the check box for installing SQL is displayed in the exit dialog box.
I defined a variable called IS_INSTALL_SQL with an initial value of 0. In the custom action, I will determine whether the user has installed SQL based on the registry, and if not installed, the IS_INSTALL_SQL is set to 1.
According to the log, IS_INSTALL_SQL is set to 1, but in the exit dialog box, the value is still 0 and the check box is not displayed.
The following is the code
[product.wxs]
<Property Id="IS_INSTALL_SQL" Value="0"/>
<Binary Id="myCustomActionsDLL" SourceFile= "$(var.CustomAction1.TargetDir)CustomAction1.CA.dll" />
<CustomAction Id="checkSQLInstallAndVersion" BinaryKey="myCustomActionsDLL" DllEntry="checkSQLInstallAndVersionAction" Execute="immediate" Return="check"/>
<InstallExecuteSequence>
<Custom Action="checkSQLInstallAndVersion" Before="InstallValidate">NOT Installed</Custom>
</InstallExecuteSequence>
[ExitDialog.wxs]
<Control Id="InstallSQLCheckBox"
Type="CheckBox"
X="135"
Y="170"
Width="220"
Height="14"
Hidden="yes"
Property="WIXUI_EXITDIALOGOPTIONALCHECKBOX_SQL"
CheckBoxValue="1"
Text="[WIXUI_EXITDIALOGINSTALLSQLTEXT]" >
<Condition Action="show">
<![CDATA[IS_INSTALL_SQL = "1" AND NOT Installed]]>
</Condition>
</Control>
The following is a log snippet.
Line 86: MyLog:The SQL version is below the minimum version
requirement and enters the installation SQL step.
Line 87: MyLog:#IS_INSTALL_SQL#:0
Line 88: MyLog:Set Property Value
Line 89: MyLog:#IS_INSTALL_SQL#:1
Line 187: Property(S): IS_INSTALL_SQL = 1
Line 317: Property(C): IS_INSTALL_SQL = 0

You only schedule the CA during InstallExecuteSequence which happens after the UI phase. Schedule it early in both, including InstallUISequence and sequence it before AppSearch, then define the CustomAction #Execute="firstSequence" for example so it only runs once and sets the value appropriately. While you have it defined as public (all upper case including underscores), ensure that doesn't change otherwise its value is reset to its default of 0 in your case when the client phase ends and the server phase starts.

Related

Set the Property value to an ini file WIX

I was setting a property value inside a Dialog using Edit Control. But when i used the same property for writing inside an ini value it is not writing the updated value and writing only old value. My WIX source code is given below(writing only important codes as my wix code is too large)
<Property Id="testNumber" Value="1122" />
<CustomAction Id="SettestNumber" Property="ModifiedtestNumber" Value="[testNumber]" />
<ComponentGroup Id="INIFileGroup">
<Component Id="IniFile" Guid="{0ded271b-9268-49e7-8c13-60c7538acc25}" KeyPath="yes" Directory="DirCfg" >
<IniFile Id="IniPath" Action="addLine" Directory="Dirtest" Key="testkey" Name="test.ini" Section="test" Value="[ModifiedtestNumber]" />
</Component>
</ComponentGroup>
<InstallUISequence>
<Custom Action="SettestNumber" Sequence="1299"/>
</InstallUISequence>
<Dialog Id="testNumberUI" X="50" Y="50" Width="375" Height="270" Title="[ProductName]" CustomPalette="yes">
<Control Type="Edit" Id="test_Number" Width="50" Height="15" X="258" Y="53" Property="testNumber" Text="{50}" TabSkip="yes"/>
</Dialog>
I am giving the value 1212 in the Control edit box and installing but inside the test.ini file it is not getting updated and value is 1122. Could someone please provide a way for me to update the Modifedtestnumber to the ini file
Note:
When i put the Custom action inside < InstallExecuteSequence/> the value inside the ini file was null
Your property need to be public (all caps TESTNUMBER) and marked with Secure attribute so that it's listed in the SecureCustomPublicProperties property. Also be aware that properties are not persisted. You need to use something like the WiX remember property pattern for the value to be loaded from the INI file during subsequent transactions such as repairs and upgrades.

How can I have a WiX Property default to null?

I am working on a set of WiX installers that are going to share a common form. Every application needs the values set, but they are going to be different for each application.
I am trying to allow for the properties (which are linked to controls) to have a default value (or not) and to allow for the property values to be set via command line.
in my "SharedDialog.wxs" I have:
<Fragment>
<PropertyRef Id="PROP1"/>
<PropertyRef Id="PROP2"/>
<UI>
<Dialog Id="SharedDialog" Width="370" Height="270" Title="[ProductName]">
<Control Type="Edit" Id="1" Property="PROP1" Wid... Indirect="no" />
<Control Type="CheckBox" Id="2" Property="PROP2" Wid...
CheckBoxValue="1" Indirect="no"/>
</Dialog>
</Fragment>
In a file for the application specific project:
<Fragment>
<Property Id="PROP1" Value="Test"/>
<Property Id="PROP2" Value="1"/>
</Fragment>
This all works for what I am trying to do, but the problem is that when I want to clear the values as so: (so they don't have a default)
<Fragment>
<Property Id="PROP1"/>
<Property Id="PROP2"/>
</Fragment>
I get this error:
Unresolved reference to symbol 'Property:PROP1' in section 'Fragment:'.
Unresolved reference to symbol 'Property:PROP2' in section 'Fragment:'.
WiX also will not let you set value to "". The problem is that as far I can tell the checkbox will always be checked if the property has a value. How can I set the property "PROP2" to "null"?
You can undefine an existing property by setting it equal to an empty string wrapped in braces like this: PROPERTY = {} in a set property custom action. This means the property doesn't exist, it is not an empty string. See the explanation here.
For properties to be available from the command line they must be PUBLIC - they are the properties that are all UPPERCASE.
Setting PUBLIC PROPERTIES secure means they can be passed from the client to the server installation process which is required for properties that are used in deferred mode custom actions. Technically this adds them to the list of SecureCustomProperties.
You can give PUBLIC PROPERTIES a default value in the Property table, and then set other values from the command line. The command line overrides the defaults:
msiexec.exe /I "C:\Test.msi" /QN /L*V "C:\log.log" TEST="MyValue" TEST2="MyValue"
See more info:
How to set a check box to "unchecked" from the msiexec command line?
Nevermind, I found the solution:
<Fragment>
<Property Id="PROP1" Secure="yes"/>
<Property Id="PROP2" Secure="yes"/>
</Fragment>

Execute a custom action before Product condition

Basically I need to verify that a certain program is not running before installation. This is done via a custom action, which sets a property, APPRUNNING:
<CustomAction Id="CheckingAppIsRunning"
BinaryKey="AppIsRunning"
DllEntry="AppIsRunning"/>
<Binary Id="AppIsRunning"
SourceFile="CustomActions.CA.dll" />
But in the message displayed, APPRUNNING seems to be null, that is, it's not set at all (should be either "0" or "1").
<Condition Message="Exit all instances of [APPNAME] before installation (APPRUNNING = [APPRUNNING]).">
<![CDATA[APPRUNNING = "0"]]>
</Condition>
<InstallExecuteSequence>
<Custom Action="CheckingAppIsRunning" Before="LaunchConditions" />
</InstallExecuteSequence>
I suppose the custom action is not executed at the moment of the condition check. What are the options to perform a condition check after a custom action?
The LaunchConditions action is scheduled to run in both InstallUISequence and InstallExecuteSequence. As long as you schedule your custom action to InstallExecuteSequence only, the property won't be set by the time LaunchConditions is fired in InstallUISequence.
You should schedule your CheckingAppIsRunning custom action in both sequences. You might also want to define it with Execute='firstSequence' attribute - this way it will run the first sequence it is met in.
This is what I mean, actually:
<InstallUISequence>
<Custom Action="CheckingAppIsRunning" Before="LaunchConditions" />
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="CheckingAppIsRunning" Before="LaunchConditions" />
</InstallExecuteSequence>
And the definition:
<CustomAction Id="CheckingAppIsRunning" BinaryKey="AppIsRunning" DllEntry="AppIsRunning" Execute="firstSequence"/>

Custom Action execution by feature

I wrote a custom action to create a scheduled task after install.
I do not want the Custom Action to run when the user does not want to create the schedule task. During installation even if I select " Feature will be unAvailable" the schtask is getting created. How do i prevent the Custom Action from executing?
You can set a condition for your CA execution:
<InstallExecuteSequence>
<Custom Action="ScheduleTaskCA" After="InstallFinalize">
<![CDATA[&feature_name=3]]>
</Custom>
</InstallExecuteSequence>
Hope it helps.
If you want to read more about CAs conditions, you can chech the link below.
Advanced Custom Action Conditions
Add to your Install execute sequence.
Actually I found out the problem. The &FeatureName = 3 tells me that the feature is to be installed, and the opposite to that, is !FeatureName = 3, which means the feature is installed already. This fixed my problem so the final solution became
&FeatureName = 3 OR (!FeatureName = 3 AND NOT (Uninstalling OR MSIPATCHREMOVE OR RemovingForUpgrade)
"MyService" is feature Name
"FEATURE_MyService" is my condition Name: I am using checkbox to set the value of FEATURE_MyService property
<Control Id="Chk1" Type="CheckBox" Height="12" Width="110" X="50" Y="199" Text="Portal Windows Service" Property="FEATURE_MyService" CheckBoxValue="0" Hidden="yes">
<Custom Action='CAction1' After="InstallExecute">
NOT Installed AND <![CDATA[(&MyService=3)]]>
<Custom Action='CAction2' Before='InstallExecute'>
<![CDATA[(&MyService=3 AND NOT Installed)]]>
<Custom Action='CAction3' After='InstallFinalize'>
<![CDATA[FEATURE_MyService AND NOT Installed ]]>

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.