Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
840 views
in Technique[技术] by (71.8m points)

windows installer - How to assign path value to Directory in WIX?

In my WIX project I have a directory structure something like this:

<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="INSTALLLOCATION" Name="FolderName">
   ...
  </Directory>
  <Directory Id="MYDIRECTORY" Name="SomeDifferentDirectory">
   ...
  </Directory>
</Directory>

Here INSTALLLOCATION represents the installation folder of my program, but I want to additionally create another directory that is outside the installation directory, for example, D:MyFolder1MyFolder2, from the example above how can I assign this value to MYDIRECTORY so that it will be created after installation completes?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't have time to test the options I list below, but they should be viable, technical possibilities. Hopefully one of the options will be satisfactory.

But, first of all: I dislike this approach of setting secondary, top-level directories - is it really needed? Can you explain the scenario? Maybe there is a more reliable way?

See the "Alternatives?" section towards the bottom for what I deem to be a better approach than to "fiddle around" with directory properties. If I were you I would read this "Alternatives?" section first - maybe it saves you a whole lot of trouble?

But the first section deals with various technical options to do what you ask:


Setting a Directory Property

There are many ways to set a directory property, off the top of my head. As I said, I haven't had time to test these options - and it is always mad to post untested advice, but you seem like someone who can help yourself with some pointers:

  1. AppSearch - you can search the system for a specific file or registry entry and set the directory property to the path found (if any).
    • Very often the path you need can be found this way - and reliably too in the sense that it is a built-in feature (and hence better tested than any custom construct from yourself).
    • You can add a custom action as well to verify that the directory found is valid - if need be. Such "verify data" custom actions can be made pretty safe since they don't change the system - but they can still cause unexpected runtime failures if you are not careful and allow them to return error codes or abort the setup.
  2. A Set Property Custom Action (Custom Action Type 51). Just set the path to something like [ROOTDRIVE]MyFolder.
    • If someone would do that I would fail the package for quality reasons (it is technically possible, but ROOTDRIVE may switch to point to a different path depending on disk space available on each drive - not good at all).
    • Know about the possibility, look for it, fix it if you find it. Don't use it. Seductive the dark side is.
    • Ironically, if I am honest, setting something to [WindowsVolume]MyFolder - may actually work, but I don't like it personally. I want nothing installed to a top-level folder on the system drive in the first place.
    • I believe WiX has the SetDirectory Element for this "set property" purpose. I think it does all the custom action work for you. Some auto-magic. I am however not sure if this feature allows PUBLIC PROPERTIES to be overridden from the command line?
    • If you set something to D:MyFolder you have to be aware that this path could at some point be missing unexpectedly (drive removed from system, new drive added (?), new DVD drive added (?), drive letter manually changed, etc...).
      • This is beyond normal "set property" actions - it is essentially "hard-coding" (see issue 5 below). Hard coding is never acceptable - for any package with generalized distribution.
      • I would prefer to target PersonalFolder (My Documents) and then redirect this to D: in Windows itself. I believe Windows will then assign a new value to PersonalFolder if it can't be found on boot. Windows Installer will then still be able to enumerate the target folders and not just get stuck or crash.
  3. Set directory as a feature directory exposed in the custom dialog in the installer GUI.

    • Mad to suggest since I have never used it, but it is an viable option I think - but requires significant testing in all installation modes (install, repair, self-repair, uninstall, modify, patching, et...) to make sure it works as desired.
      • Quick update: I did a smoke test, it works, but it is not trivial to do I would say. See mock up GUI sample and some WiX snippets in next section below.
    • This involves adding a separate feature for the components set to this feature directory. Then you set the ConfigurableDirectory attribute of the FeatureElement in your WiX source equal to the PUBLICPROPERTY holding the directory path.
    • You should now be able to set this directory from the WiX GUI if you use the dialog set Mondo (<UIRef Id="WixUI_Mondo" />) - from the "Custom" dialog. There is a step-by-step sample using Visual Studio to update a WiX source file to use Mondo here: WiX installer msi not installing the Winform app created with Visual Studio 2017.
    • The GUI selection you make (directory) will be assigned to the property you specified as the ConfigurableDirectory for the feature.
    • Somehow you must set the directory property to something meaningful for a silent install - when the GUI is skipped - or you could abort installation if nothing is defined for the property on the command line.
    • I would check for a valid directory while at it and protect against generalized lunacy such as installing to the system folder, installing straight to C:, installing into existing folders for other products, etc... - "...users are amazingly creative when it comes to exercising a system in unexpected ways" - Grady Booch - words to live by, and what a cool name - and hair - :-).
  4. A regular, immediate mode custom action (not a set property custom action) which sets a property with a call to Session.Property = "SomeValue" somewhere in the code. Each type of custom action type does this "property set" slightly differently (custom action types: VBScript, C++, DTF / C#, etc... See documentation from Advanced Installer for how this can be done).

    • I am always telling people to avoid custom actions, and it is definitely true for read-write custom actions: Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?.
    • I do, however, use read-only custom actions set to suppress errors and not return errors that roll back the setup when needed. This allows you some power to inspect the system as you see fit to determine what to set to the property in question.
    • Crucially such immediate mode read-only custom actions require no rollback feature since they make no system changes, they don't run elevated either, and most of them "live in the GUI sequence" and are used to get data and settings from the user - or checking various conditions and states of the target system - just inspecting things (they are often also needed in the silent install sequence if the GUI is skipped).
    • Remember that the GUI sequence is skipped in silent installation mode, so your custom action must live in both sequences. You can condition it to run only once though.
  5. Some people even hard code paths in the property table, or using a set property custom action to assign C: to a property at runtime - not at all acceptable. This will break - it is merely a question of time. On computers without a C: drive it will not install at all - for starters.

    • Not sure if such a property, set in the property table would be overridden during directory resolution and costing - I have never bothered to try - it is not a solution and I just want to state that to prevent its use.

    • A set property custom action assigning C: or similar to a property will appear to work, but will blow up in unexpected ways. Guaranteed.

    • Again: if you can help it, don't deploy to a separate, top-level folder.

  6. I have heard some people - in corporate, standardized environments - use an environment variable to define such installation folders. I have never used it for production, never tried it for testing and don't like it as an option.

Keep in mind that public properties can be set at the command prompt - and hence potentially override whatever logic you add to set it yourself. Maybe add a custom action to check for values coming in from the command line, and either accept it or abort the setup if it is wrong.


WiX-installer With Configurable Feature Directory

Here is the GUI screenshot of a WiX installer with configurable feature directory:

enter image description here

The browse button seen above is only available for features that has the ConfigurableDirectory attribute specified pointing to a custom directory property (ignore the C: entry in the screenshot above - just a hiccup):

<!-- A standard feature -->
<Feature Id="ProductFeature" Title="MinimalShortcutTester" Level="1">
   <ComponentGroupRef Id="ProductComponents" />
</Feature>

<!-- A configurable directory feature -->
<Feature Id="FeatureDirectory" Title="FeatureDirectory" ConfigurableDirectory="MYCUSTOMDIR">
        <!-- your stuff here -->
</Feature>

And elsewhere in the WiX source, the actual configurable directory:

<Directory Id="MYCUSTOMDIR">
     <!-- Mock-up GUID that MUST be changed, custom target directories do not function with auto-GUIDs -->
     <Component Id="MyFile.exe" Guid="{00000000-0000-0000-0000-000000000000}" Feature="FeatureDirectory">
         <File Source="C:SourceControlMyFile.exe" />
     </Component>    
</Directory>

I would use an extra custom action to default this MYCUSTOMDIR directory well, or to inspect the choice made by the user for validity. This is not entirely straight forward, but must be dealt with in each case.

On second thought, I might use a set property custom action to default the MYCUSTOMDIR directory to a sub-folder of PersonalFolder, then allow the user to override it on install. Now you have to read back the user choice on modify and repair (and other installation modes), or else you will default to PersonalFolder and whatever sub-folder you specified in other install


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...