WiX Checkbox property only working if default valu

2019-03-02 20:54发布

问题:

As I understand it, in WiX, a checkbox is checked if the property is not null. So in order to default a checkbox to "Checked", the property must be defined apart from the checkbox.

Given that, I have a checkbox that allows the user to choose whether or not they want a shortcut added to their desktop. Originally it was set up to be checked by default, but I'm now trying to change it so that it is unchecked by default. However, when I remove the property definition so that it won't be checked, the option no longer works. The installer won't add the shortcut whether the checkbox is checked or not. Here's how the checkbox was originally defined:

<Property Id="ADD_DESKTOP_SHORTCUT" Value="1" />

<Control Id="ShortcutCheckbox"
         Type="Checkbox"
         Property="ADD_DESKTOP_SHORTCUT"
         CheckBoxValue="1"
         Integer="yes"
         Text="Add Desktop Shortcut" />

The Desktop shortcut feature is defined as follows:

<Feature Id="DesktopShortcut" Title="Desktop Shortcut" Level="0">
  <ComponentRef Id="CMP_DesktopShortcut" />
  <Condition Level="1">
    <![CDATA[(ADD_DESKTOP_SHORTCUT) or (REMOVE = "ALL")]]>
  </Condition>
</Feature>

The above works, but as soon as I remove <Property Id="ADD_DESKTOP_SHORTCUT" Value="1" /> it no longer adds the shortcut regardless of the checkbox selection.

I've also tried leaving the property defined, but changing it's value like this:

<Property Id="ADD_DESKTOP_SHORTCUT" Value="{}" />

This doesn't work either. I get an error. (Error code 2892)

Can anyone tell me why removing the default value causes the option to stop working? And/or how to get it to work?

回答1:

{} can't be used in the property table or the type 51 setproperty custom action. It only applies to a setproperty control event. You can have the property not set by simply declaring it and not giving it a value.

<Control Id="Custom" Type="CheckBox" X="20" Y="80" Width="320" Height="18" Property="MYPROPERTY" CheckBoxValue="Checked"/>
<Property Id="MYPROPERTY" Secure="yes"/>


回答2:

If you go with a component condition, you should be aware that the component is installed if the condition is null or evaluates to true (not sure about that null thing, but that is what the SDK says).

I would suggest checking an actual value to avoid that null-trap:

  <Property Id="ADD_DESKTOP_SHORTCUT" Secure="yes" Transitive="yes" />

  <Component Id="CMP_DesktopShortcut">
     <...>
     <Condition>ADD_DESKTOP_SHORTCUT="1"</Condition>
  </Component>

So that is ADD_DESKTOP_SHORTCUT="1" instead of just ADD_DESKTOP_SHORTCUT. You can obviously include Value="1" for the property element to make installing the shortcut default.

Note that I set Transitive="yes" to account for the fact that you might allow this setting to change in the setup's maintenance dialogs when it runs (not just the install dialogs), and then you can re-evaluate the component condition - potentially removing the component if the user changed the selection. (Transitive: "If this bit is set, the installer reevaluates the value of the statement in the Condition column upon a reinstall".)

I assume you install per-machine (ALLUSERS=1) and install the shortcut to the desktop shared by all users - to ensure all users can launch the application (otherwise you need to make further mechanisms to get the per-user shortcut added when you log in as another user).

A "Set Property Custom Action" (Type 51) can indeed undefine a property by setting its value equal to {} provided it runs prior to CostFinalize. I just tested this in the InstallExecuteSequence and it works fine.

Chris is probably talking about the setup GUI (dialogs show after the GUI version of CostFinalize has completed), in which case you should use the SetProperty ControlEvent instead of a SetProperty custom action - as he states (I didn't bother to test the SetProperty custom action here).


The below is no longer relevant since you seem to have abandoned the use of a conditioned feature, but with regards to your original question: "Can anyone tell me why removing the default value causes the option to stop working?"

Feature Condition: When you don't set the ADD_DESKTOP_SHORTCUT property at all, your feature condition is not true, and your feature will hence not switch from its default install level 0 (don't install) to install level 1 (install):

<Feature Id="DesktopShortcut" Title="Desktop Shortcut" Level="0">
 <Condition Level="1">
     <![CDATA[(ADD_DESKTOP_SHORTCUT) or (REMOVE = "ALL")]]>    <= True only on uninstall
 </Condition>
</Feature>

Feature Condition Problem: Note that any feature set to Level=0 as default will not be extracted during an administrative install at all (!), regardless of any feature conditions setting the feature to install. This is quite mad to be honest, but seems to be how admin installs currently work. I can not see any benefits to this design.

You can avoid setting any features to Level=0 by setting Level=1 as default and then set them to Level=0 with a feature condition that evaluates to true. This way the feature may be hidden in a regular installation, but all features - with associated files - are extracted during admin installation.