How can I require at least one of two optional components in WiX?
Asked Answered
C

4

5

I am using WixUIFeatureTree to offer the user an option of what components of my application they want to install... One of my features has two optional features within it, at least one of which must be installed for the program to work. I don't want to force the user to install either particular one, but I'm at a loss as to how to force them to choose at least one.

Here's the relevant portion of my current WXS:

    <Feature Id="Main" Title="Product Name" Level="1" Absent="disallow" Display="expand" AllowAdvertise="no"
             Description="This is the application, and is a required component"
             >
        <ComponentRef Id="Baseline" />
        <ComponentRef Id="Shortcuts" />
        <Feature Id="Option1" Title="Plugin #1" Level="2" Absent="allow" AllowAdvertise="no">
            <ComponentRef Id="Plugin1Component" />
        </Feature>
        <Feature Id="Option2" Title="Plugin #2" Level="3" Absent="allow" AllowAdvertise="no">
            <ComponentRef Id="Plugin2Component" />
        </Feature>
    </Feature>

I'm guessing that I'm going to need some kind of Custom Action inserted at the right point of the sequence guaranteeing that one or the other is selected for install, but no clue how to do that, or if it's even right. All help appreciated!

Cana answered 2/9, 2009 at 1:29 Comment(0)
I
4

I realize this is an old post, but this is how I solved this using WIX v3.7 with the UI FeatureTree:

<Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">&amp;MyAppClientFeature=3 OR &amp;MyAppPrinterFeature=3</Publish>

Full FeatureTree override code:

<UI Id="WixUI_FeatureTreeCustom">
    <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
    <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
    <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />

    <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
    <Property Id="WixUI_Mode" Value="FeatureTree" />

    <DialogRef Id="ErrorDlg" />
    <DialogRef Id="FatalError" />
    <DialogRef Id="FilesInUse" />
    <DialogRef Id="MsiRMFilesInUse" />
    <DialogRef Id="PrepareDlg" />
    <DialogRef Id="ProgressDlg" />
    <DialogRef Id="ResumeDlg" />
    <DialogRef Id="UserExit" />

    <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>

    <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg">NOT Installed</Publish>
    <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>

    <Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
    <Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg">LicenseAccepted = "1"</Publish>

    <Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="1">Installed</Publish>
    <Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg" Order="2">NOT Installed</Publish>
    <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">&amp;MyAppClientFeature=3 OR &amp;MyAppPrinterFeature=3</Publish>

    <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="1">NOT Installed OR WixUI_InstallMode = "Change"</Publish>
    <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
    <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3">Installed AND PATCH</Publish>

    <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>

    <Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="CustomizeDlg">1</Publish>
    <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
    <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
    <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
</UI>

<UIRef Id="WixUI_Common" />

I hope this helps someone out.

Infatuate answered 28/4, 2013 at 7:35 Comment(0)
W
2

I think what you actually want to do here is put a condition in the <Publish> element for the Next button to not enable it until your conditions are met. Something like:

<Publish Dialog="..." Control="Next" Event="NewDialog" Value="...">OptionalPkg1Selected OR OptionaloPkg2Selected</Publish>

What I don't know is how to set those conditions based on which components are checked, though there has to be some way to do it so that the right components get installed later on...

Wynnie answered 8/9, 2009 at 17:49 Comment(2)
Yeah, I would try this first. Otherwise, I don't believe WiX has an "either or" available. You could also have a custom dialog screen where the user has to select one option or the other.Berkman
I realize this is an ancient post, but thank you Jeff. Your post pointed me in the right direction. I posted my solution, based off yours, as an answer below (the one that worked for me at least, in WiX v3.7).Infatuate
A
1

How about using the Feature state as a condition?

Something like (&Option1=2) AND (&Option2=2)

Here is a link for better understanding:

MSI Advanced Custom Actions

Anopheles answered 9/10, 2009 at 17:8 Comment(1)
This is what I ended up doing. I used Feature states as a condition to force one of the two options into Level 0 (no install)Dump
I
0

I don't have time to run a technical test right now, but just want to point you in the direction of the INSTALLLEVEL Property. It's a rather counter-intuitive concept related to feature selections. Essentially there is an overall INSTALLLEVEL of the installation, which is a number between 1 and 32,767 and features each have an Install Level property, which is a number between -32,767 and 32,767. If a feature's Install Level value is less than or equal to the product's INSTALLLEVEL property, the feature is turned on: http://kb.acresso.com/selfservice/viewContent.do?externalID=Q103232

Generally you use this to set the default feature states and to disable hidden features on operating systems where the feature isn't supported. However, you may be able to use these properties along with a custom action run on the dialog's next button event to enforce selection of at least one of your features.

And yes, MSI dialogs in general make no sense, and they are way to complicated to work with. In some cases I have replaced a single dialog in a sequence with a regular windows exe dialog to work around limitations in the overall MSI GUI concept.

I'll have a think if there is an easier way to do this. It sounds like this is very urgent though, so perhaps you want to check with the deployment communities and peruse some of the best deployment sites:

Interregnum answered 15/9, 2009 at 2:41 Comment(2)
Yes in fact I am using the INSTALLLEVEL feature to set the default components (actually, picking one of the two). However, nothing stops the user from turning both of them off, which is what I want to accomplish.Cana
How about hiding the features in the feature tree, and then providing a radio button style choice in the next dialog? You need some heavy tweaks to the MSI dialogs to do this, but there is an article on Installsite on how to do it. Just want to ask before I dig it up.Pose

© 2022 - 2024 — McMap. All rights reserved.