3

I need the User to be able to set multiple different target directories for my installation.

I have this directory structure:

<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="ProgramFilesFolder">
    <Directory Id="DCOMPANY" Name="MyCompany" >
      <Directory Id="DMAIN" Name="MainDir">
        <Directory Id="DPART1" Name="Part1"/>
        <Directory Id="DPART2" Name="Part2"/>
      </Directory>
    </Directory>
  </Directory>
</Directory>

I also have these Properties here

<Property Id="WIXUI_INSTALLPATH" Hidden="yes" /> 
<Property Id="VARIABLE_PATH_DPART1" Value="DPART1" />
<Property Id="VARIABLE_PATH_DPART2" Value="DPART2" />

To override the Single InstallDirDialog, I've copied the files WIXUI_InstallDir.wxs and InstallDirDlg.wxs. I duplicated InstallDirDlg.wxs and added the numbers 1 and 2 to the end of the files, prefixed all of the three with custom_ and changed their UI-Tags correspondingly:

Now, in the custom_WIXUI_InstallDir.wxs, theres this block that I changed a little so I would expect MY Properties are being set by the Actions:

  <Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="custom_InstallDirDlg1">LicenseAccepted = "1"</Publish>


  <Publish Dialog="custom_InstallDirDlg1" Control="Back" Event="NewDialog"
  Value="LicenseAgreementDlg">1</Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="Next"    
  Event="SetTargetPath" Value="[VARIABLE_PATH_DPART1]" Order="1">1</Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="Next" Event="DoAction"
  Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="Next" Event="SpawnDialog"
  Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND
  WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="Next" Event="DoAction"
  Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND
  WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="Next" Event="NewDialog"
  Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR
  WIXUI_INSTALLDIR_VALID="1"</Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="ChangeFolder"
  Property="_BrowseProperty" Value="[VARIABLE_PATH_DPART1]"
  Order="1">1</Publish>
  <Publish Dialog="custom_InstallDirDlg1" Control="ChangeFolder"
  Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>

  <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog"
  Value="custom_InstallDirDlg1" Order="1">NOT Installed</Publish>

In custom_InstallDirDlg1.wxs I also changed this line to my path variable:

    <Control Id="Folder" Type="PathEdit" X="20" Y="100" Width="320"
  Height="18" Property="VARIABLE_PATH_DPART1" Indirect="yes" />

When I compile now, everything gets created and when I run the Installer, when I click on the "Change..." Button or the "Next..." button the Installer freezes for approximately 30 seconds and then Says "The specified Path DPART1 is unavailable."

When I look at the sources of the custom actions that are being called in all those CDATA blocks I see that those only ever care for the WIXUI_INSTALLPATH and don't accept anything given to them. So it's pretty much using indirection for that.

I've also read somewhere that this dialog can be reused to have the User enter multiple target paths but I can't figure out how.

Please help :)

Stein Åsmul
  • 34,628
  • 23
  • 78
  • 140
Ravior
  • 481
  • 1
  • 9
  • 24
  • I don't have time to read this in detail at the moment, but please have a look at this answer: [WiX-installer With Configurable Feature Directory](https://stackoverflow.com/a/48490880/129130) (towards the middle, and also the rest of the answer if it looks relevant). – Stein Åsmul Feb 06 '18 at 12:15
  • Thank you very much. This actually helped me a lot. Sadly I didn't find it because I always looked for "multiple custom target directories" and such. I can give you the bounty if you want :D Actually at the moment I can't even upvote your answer on this post you linked there because I've not enough Reputation left though :D – Ravior Feb 06 '18 at 20:22
  • Don't worry about the bounty for now, just give that information a go if it is helpful. I didn't test it much - please do test and let us know what you find. That dialog is from the WiX Mondo dialog set btw - but I assume you got all of that sorted out? [I describe setting up a minimal WiX compile with the Mondo dialog set here](https://stackoverflow.com/a/47972615/129130). – Stein Åsmul Feb 06 '18 at 20:53
  • Yes, I got it sorted out with your idea of using features to differentiate the parts of the software; so that each could be installed to different directories. I also made sure that none of these "Features" could be disabled by setting their "absent" flag to false and also set the corresponding components to location="local" so that the option "install from network" could not be selected by the user. – Ravior Feb 07 '18 at 07:00
  • OK, great. Please be sure to check what happens in different installation modes with this approach (install, repair, modify, self-repair, patching, etc...). Properties are not normally persisted by MSI automatically, but feature directories might be - unfortunately I haven't used them enough to be sure. Also be aware that they might be possible to set and hence override at the command line. I should test this tomorrow. If I get it done, I will let you know. – Stein Åsmul Feb 07 '18 at 07:05
  • Did you persist the properties to the registry and read them back on major upgrades? It looks like directory properties are persisted for most installation modes, but not for a major upgrade. This could cause you a lot of grief once you upgrade (you will be back to default folders). I'll update my answer below a little. – Stein Åsmul Feb 08 '18 at 00:51

1 Answers1

2

Maybe I will add it as an answer so you can accept it like you say - and maybe upvote. Then just let the bounty run out - I don't think it will work since you don't have the reputation yet.

I don't have time to read this in detail at the moment, but please have a look at this answer: WiX-installer With Configurable Feature Directory (towards the middle, and also the rest of the answer if it looks relevant). These are "feature directories" that can be linked to an actual directory property as described in the link.

The sample above uses the WiX Mondo dialog set. I describe setting up a minimal WiX compile with the Mondo dialog set here. Essentially a "Hello WiX" project, but you have this down already. Just adding it in case someone else may find it helpful.


UPDATE: My brief testing seems to show that such feature directories are persisted by the system for most installation modes, but not for major upgrades. To read the previous settings for these custom folders, you need either an AppSearch or a custom action I'd say, and you should make your setup persist the directory properties in the registry.

Some pointers

These are just some suggestions from quick testing. Please, as always, test thoroughly yourself. There is a lot of what I call "conspiratory complexity" in Windows Installer - problems surface unexpectedly - for example when you try to deliver an upgrade.

Persisting your properties in the registry during install (your feature directory properties):

<!--Put this inside a component-->
<RegistryKey Root="HKLM" Key="Software\MyCompany\MyApp" ForceCreateOnInstall="yes">
  <RegistryValue Type="string" Name="MYCUSTOMDIR" Value="[MYCUSTOMDIR]" KeyPath="yes"/>
</RegistryKey>

<!--Put this inside a component-->
<RegistryKey Root="HKLM" Key="Software\MyCompany\MyApp" ForceCreateOnInstall="yes">
  <RegistryValue Type="string" Name="MYCUSTOMDIRTWO" Value="[MYCUSTOMDIRTWO]" KeyPath="yes"/>
</RegistryKey>

And important!: this will write to HKLM\SOFTWARE\WOW6432Node\MyCompany\MyApp - the 32-bit section of the registry on a 64-bit OS. You may need to write and read from the 64-bit section. If so, just add the Win64="yes" attribute to the Components and the RegistrySearch elements.

A link: http://robmensching.com/blog/posts/2010/5/2/the-wix-toolsets-remember-property-pattern/

Next read them back with a registry search:

<Property Id="MYCUSTOMDIR">
  <RegistrySearch Id='MYCUSTOMDIR' Root='HKLM' Key='Software\MyCompany\MyApp' Name='MYCUSTOMDIR' Type='raw' />
</Property>

<Property Id="MYCUSTOMDIRTWO">
  <RegistrySearch Id='MYCUSTOMDIRTWO' Root='HKLM' Key='Software\MyCompany\MyApp' Name='MYCUSTOMDIRTWO' Type='raw' />
</Property>    

In an ideal world this should suffice for your purpose. I did not have time to test what happens when these properties are set at the command line for an upgrade (which could happen).

To create a major upgrade for testing you can basically just bump up one of the first three digits of your version number and compile a new MSI (rename the old MSI in the output folder to preserve it) - and generate a new product GUID (unless you have it set to auto-generate, in which case the version bump is enough). An MSI version number should incidentally have only 3 digits to be compliant to MSI standards.

Stein Åsmul
  • 34,628
  • 23
  • 78
  • 140