How to prevent changes in Directories after UISequence - wix

I am linking my product with other libraries, trying to make it easier to install a set of directories in multiple installations. The purpose is to reuse the xml code, problem is they have to be installed in the Root directory per customer requirement.
So I have my ComponentGroups inside the WixLibrary.
I set up my directories in the Wix Application.
But after CostFinalize just before Installation the Directories are reset to their default values and not the ones chosen by my user during the Dialogs Sequence.
Is there a way to prevent this?

Ok, First things first:
The problem is that after CostFinalize and all UI operations my directories where replaced with the default values.
The problem started when I linked two different libraries that used the same global directory.
The folder is set in the root folder of Windows (Per customer Requirement) and then set up to a default value. Then we attach a Property just like we would do it for the WIXUI_INSTALLDIR, overall we have the following:
One root folder for the specific files of the installer
A library that installs files to 4 directories that are unrelated to that root directory.
Another library that installs files and runs scripts to 1 directory of those 4 external directories. This library is the only specifc to our install.
Linking all that is a problem of its own, it has to be done in the Product, in the UI, and using the PropertyRefspecified in the external library. Furthermore, keep in mind that every PathEdit has to be set to Indirect="yes", and you have to set all indirect Properties that point to your Directory in the UI
To fix the problem is really simple, Microsoft Installer rechecks all our folders after the user has set them up during the Install Sequence, so we need to prevent any changes after the user has changed it during the UI Sequence. Thus Properties to the rescue.
Here is an example, in the UI you set a freeze folders to each folder you want to set in the InstallUISequence
<Property Id="SETFOLDERFREEZE">0</Property>
<CustomAction Id="caSetPreventChanges" Property="SETFOLDERFREEZE" Value="1"/>
Then in your Product you link that property.
<PropertyRef Id="SETFOLDERFREEZE"/>
<SetDirectory Id="SPECIFIC_FOLDER" Value="[WindowsVolume]MoreStuff" Sequence="both">
<![CDATA[SETFOLDERFREEZE<>"1"]]>
</SetDirectory>
<Property Id="EXTRAFILES_INSTALLDIR" Value="SPECIFIC_FOLDER"/>
You use the Property EXTRAFILES_INSTALLDIR in your specific UI for that project and you use SPECIFIC_FOLDER in your reusable Library.
It's a mess... but allows reusability, and setting some simple properties and custom actions beats setting up the Files and Folders all over again, specially if there are hundreds of them.

Related

Wix property evaluation

How to use FileSearch result as condition in Component section.
I want to get something like this:
<Property Id=\"CONFIG_XML_EXISTS\">
<DirectorySearch Id="CheckForConfigXml" Path="[INSTALLDIR]\">'
<FileSearch Id="ConfigXmlSearch" Name="config.xml" />
</DirectorySearch>
</Property>
...
<Component Id="c_DefaultConfig.xml" Guid="{1AAB0AFD-B763-4A55-8585-B0AD4D8CE23C}">
<File Id="f_default_config.xml"
Name="default-config.xml"
Source="$(var.SourceRoot)\config.xml"/>
<Condition>CONFIG_XML_EXISTS</Condition>
</Component>
I don't know why but property wix doesn't want to evaluate CONFIG_XML_EXISTS.
Because that search happens very early in the install, the most likely reason is that INSTALLDIR has no value. You haven't said whether you're doing a fresh install or an upgrade, so it's not clear where you think it might be getting its value from.
I'd also point out that the purpose of that source code is apparently to prevent the install of a file if there is one there already, so:
If INSTALLDIR turns out to be the application folder (typically program files) where your files are installed then users can usually change this location, so it's not clear the file is going to be where you expect it to be.
The file overwrite rules prevent incoming files from overwriting modified data files (modify date > creation date) so if that config file has been changed it won't be overwritten and you don't need to do the check.
In your comment you say "My installer must create file config.xml only if there is no such file in target(install) directory. If such file exists, my installer must create file with name template.xml". I think that perhaps the easiest way to do this is in the application after the install has finished, or possibly in a custom action after all the files have been installed. There seems to be no good way to do this before the install because INSTALLDIR is unpredictable. I've seen this kind of problem solved by installing the XML files to (say) User's Application Data, and after the files are installed then the application or a custom action can see what files are there (or not) and get them from User's Application Data.

Upgrading doesn't update VirtualStore file

I haven an installer which must run with elevated admin rights if UAC is enabled. This works fine. When I upgrade the app (using the MajorUpgrade element) the app gets uninstalled and reinstalled correcly.
During runtime the app attempts to change some files in the program files folder which places copies them items in the users virtualstore. These do not get removed during uninstall.
During the upgrade/reinstall process, is there a correct way to delete the application file copies, for all users, in the VirtualStore?
Files placed into a virtual store are, by definition of who wrote them and when, per-user data files. Such files typically should not be removed during uninstallation. If the files in question are not actually per-user data files, the application that caused them to be written should be fixed to write to a proper location, update them in a controlled fashion, or even not write them at all.

Windows Installer in XML

When uninstalling my app, I'd like to configure the WiX setup to remove directories and like user settings and user data I want add a dialog with two check boxes and optionally remove all the files that were added. It looks like the uninstaller removes only the directories and files that were originally installed from the MSI file .
In other words, I want to give user a chance to Delete his data with a dialog while uninstall is called ?
Is this possible through WiX without resorting to custom actions? Any help would be appreciated.
To do this without using custom actions, see the WiX documentation regarding the RemoveFile and RemoveFolder elements. You can use these to remove files and folders on uninstallation. RemoveFolder will only work if the folder is empty.
Note that if the files are located in the user's application data directory, you will only be able to do this for the user that is uninstalling the application. You cannot easily do it for all users.

how to copy a file and then conditionally remove it

(I'm newbe in Installer world so I'm still not sure what is right what is wrong. Anyway.)
I make a installer for service which uses desktop database. The database file should somehow be copied during first installation, be intact during upgrades and finally removed during uninstall.
As far I know, I can't add the database file as a directory component - 'cause installer will automatically remove it during uninstall. On the other hand, if I set the Persistent attribute, the database file will be NEVER removed by installer (even, if I will create separate component with RemoveFile element).
The above leads me to thinking, that I can't add the database file as directory's component.
So what are other options?
Is it possible to include a file into installer file (msi) and then copy the file with custom action to target folder?
Then deletion could be solved with RemoveFile element and condition base on UPGRADINGPRODUCTCODE property.
What do you think, guys?
If you are going to be using a custom action, why not create a custom action the will remove the file on uninstall. I have a custom action like that in a couple of my installers due to updates that happen to the target folder after the program has been running for a while. this just ensures a clean uninstall with no files laying around.

Using WiX, how to install single file to (potentially) multiple sub-directories, based on what is available at install time?

I'm using WiX, and would like to know the .wxs necessary to take a file and install it to every available sub-directory of a particular location. This could mean 0 or more final installation locations, determined at install time based on the currently existing directory structure. For example, if I started the install with:
\target
\subdir-1
\subdir-2
Then at the end of the installation my file would be in \subdir-1 and \subdir-2. If on the other hand these directories did not exist on the system when the install was started, my file would not be installed at all and no sub directories would be created.
Afaik this is not possible with WiX (because it is basically against the nature of MSI to install a component into several locations).
You could either
create a different component for each subfolder, or
use a custom action to copy the component to all subfolders.
In the latter case you should also provide a corresponding CA for uninstallation which removes all the files from the subfolders again.
EDIT: Seems my above answer is not totally correct. MSI supports duplicating files using the DuplicateFile tables and WiX 3.0 also provides a mechanism called "smart cabbing". Both are mentioned in a blog post by Aaron Stebner.
Not without a custom action, you need to write a custom action that will do that.
The latest and greatest in custom actions is the DTF (and here) framework that comes with Wix3.
If you are targeting Vista (or Win2k8, not sure about Win2k3), you can use mklink.