How to modify xml on wix repair - wix

I have an installer that is created with WIX and modifies a config via XmlFile, however I believe that the Wix Util Extension does not perform these actions on repair. This is causing problems when trying to perform a self-healing installer. Is there any way to accomplish what I am looking for

By piecing together a bunch of sources I came up with the following:
<Property Id="REINSTALLMODE" Value="amus"/>
<SetProperty Id="REINSTALL" Value="ALL" After="AppSearch">
<![CDATA[Installed AND REMOVE<>"ALL"]]>
</SetProperty>
Which forces a REINSTALL = ALL if it is not a remove or install

I have a similar scenario. Properties can be edited by the user through the UI, which are stored/loaded via the Registry and written to configuration files. Beyond Justin's answer, Secure="yes" must be set on each property, or MSI will ignore it (the log will show "Ignoring disallowed property").

Related

How to restrict user to change feature in case modify and upgrade in installer?

I have a installer which asks the user to select feature. Whatever user selects, it will never be changed in case of modify and upgrade the installation. For example:
There are three features in my installer which are below:
<Feature Id="Standalone" Title="Standalone" Level="2">
</Feature>
<Feature Id="CentralCase" Title="Central case" Level="2" >
</Feature>
<Feature Id="MiddleEF" Title="Middle Ef" Level="2" Display="expand">
<Feature Id="GUI" Title="Client" Level="3"></Feature>
<Feature Id="AppServer" Title="Application Server" Level="3">
</Feature>
</Feature>
Now suppose user starts the installation and select the first feature which is standalone and install it. Now if user wants to modify, he should not allowed to change feature or even if user wants to upgrade, user should also not allowed to change feature. He can only upgrade what he selected at first time. Is there any way to do this?
ARPNOMODIFY: I guess it depends how critical it is that these features never change. You can set the ARPNOMODIFY in the MSI to
1 and there will be no button to invoke Modify from:
<Property Id="ARPNOMODIFY" Value="1" Secure="yes" />
Disclaimer below. Here be dragons.
msiexec.exe: However, you can still invoke modify by launching the MSI file itself (the default dialog sets should correctly disable the modify button though), but worse: you can go via the msiexec.exe command line and change anything you want:
msiexec /i "MySetup.msi" ADDLOCAL=MyFeature
This might be OK since it would appear to be seldomly used. However, you should be aware that remote management systems often rely on the msiexec.exe command line to handle MSI deployment, and as such the deployment system could be used to change feature state easily (via the deployment tool GUI, no command lines to deal with).
Custom Action: I don't know of an auto-magic way to abort setup if the user tries to modify the feature structure invoked via the msiexec.exe command line, but I suppose you can use a custom action maybe right before InstallInitialize in the InstallExecuteSequence to abort the installation if ADDLOCAL, REMOVE or ADVERTISE are set? If you do not condition this custom action properly, it could cause a package that won't uninstall at all or upgrade properly.
Some unverified conditioning suggestions: How to execute conditional custom action on install and modify only?
MigrateFeatureStates: For a major upgrade the GUI will not run as if it is running modify, but a fresh installation (since the product GUID is new). Hence the original installation GUI is shown and not the modify one. Accordingly you might need to disable some GUI controls or hide whole dialogs to prevent feature selection (not sure in WiX default dialogs). Added a link for that below. The standard action MigrateFeatureStates will take care of preserving the feature installation states between versions, provided you haven't done anything drastic to the feature structure. You enable this standard action to run in the Upgrade table. Should be default to run in WiX MSIs I think.
UPDATE:
Preselected Property: There is a special property called Preselected that is to automatically hide feature selection. You can try to set it or check whether it is set automatically by WiX to see if it hides feature selection. I have honestly never tried it.
Some Further Resources:
Hiding whole dialogs: Wix, custom dialog when previous version exists

Wix: Reschedule RegisrySearch and set property in Merge Module

I have a merge module which searches for some registry locations to read values and save to Properties. Here is the code segment:
<Fragment Id="RegSearch">
<Property Id="HOST_APP_PATH" >
<RegistrySearch Id="HOST_App"
Root="HKLM"
Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\HOST.exe"
Name="Path"
Type="raw"
/>
</Property>
<Property Id="HOST_ROOT_PATH" >
<RegistrySearch Id="HOST_Root"
Root="HKLM"
Key="SOFTWARE\HostApplication\Installation Info"
Name="HOST_Root"
Type="raw"
/>
</Property>
Windows Installer puts this search in AppSearch custom action.
Problem: AppSearch executes this search very early, before WriteRegistryValues of Host Installer, it won't get any values and properties with this search won't be defined, because registry to search was never written there.
Question 1: Can we reschedule this registry search from merge module after WriteRegistryValues of Host Installer?
Question 2: Is there any other way to search registry after Host Installer executes WriteRegistryValues? Probably with some custom action?
AppSearch is a standard action provided by the windows installer and by design is intended to run very early. This is because it's frequently used by the LaunchConditions standard action to decide if an installation can continue or not. It's also useful for deciding whether features and components should be installed.
MSI is a very opinionated framework. I suspect that there is something wrong with your current design that is going to be incompatible with MSI.
Is host installer the same MSI or a different MSI? Assuming it's the same, why couldn't you just put your data in some MSI properties and use those properties to write to the registry? Then you wouldn't need to read the values back in because you'd already have them in properties.
What do you need these properties for after writing them to the registry? Usually writing them to the registry would be the end game. I'm not sure what else you are doing next.
If host.msi is a different MSI, why are you having one MSI install another MSI? That's not MSI design. In this case you would need a bootstrapper. Host MSI would run first then this MSI. But even then it's kinda strange that a second MSI would depend on properties set by a first MSI. I'd think the bootstrapper UI and Application would gather this information and pass it as secure custom public properties to both MSIs.
To answer question 1: No a merge module can only insert actions into the sequence. It can't reschedule actions. 2: You would have to use a custom action. But as I said above, this feels like the wrong path to me.

Avoid uninstall when WiX AllowSameVersionUpgrades is Yes?

I have the WiX's Product Id="*" and AllowSameVersionUpgrades="yes", so I can have 1 installer with different features (different sample images, but same .exe).
And I want to be able to install the multiple versions in the same machine so only the new features are added and the old features remain in the folder. But the old features are always being deleted. Is there a way to handle the correct way, maybe using Custom Actions?
For anyone with a similar problem the solution I've found was create a property:
<Property Id="DELFILES" Secure="yes"/>
Secure="yes" is very important otherwise the property's value won't be read when running the installer.
And then add this condition for the custom action:
<![CDATA[(REMOVE = "ALL") AND (DELFILES = "TRUE")]]>
Finally to install I just call the .msi and pass the parameter:
MsiExec.exe /x MyInstaller.msi DELFILES="TRUE"

MSIEXEC using command line REINSTALL not using original INSTALLDIR

I am trying to configure Wix to build my msi to only perform build versions (1.0.x) of my product in conjunction with the REINSTALL property, my problem is that when I run the command line: MSIEXEC.exe /i my.msi /l*vx build-inst.log REINSTALL=ALL REINSTALLMODE=vamus it fails to do anything.
I have checked the msi log and found that it is looking for the existing product in the default folder (.\program files (x86)...\myproduct) yet when I installed it the first time I actually used a custom path (c:\myproduct). It was my impression that using REINSTALL the installer would use the installed path of the original product.
Is this actually the case? Should I be specifying the INSTALLDIR on my command line? I would rather not as this is meant for use by clients and I cannot guarantee I will know where the product was installed.
This method of performing "build" upgrades has been suggested in a couple of places but I can not find anything explaining any need to specify the INSTALLDIR
Is there any way to configure this in Wix?
Thanks
Kieran
The easiest solution would be to store the installation directory in the registry and look it up upon reinstalling.
To look up your registry value, you'd use something of the sort:
<Property Id="INSTALLDIR">
<RegistrySearch Id="InstallLocation" Root="HKCU"
Key="SOFTWARE\Company\Product" Name="Location" Type="raw" />
</Property>
If the registry value isn't found, the INSTALLDIR property will be set to your directory structure.
Rob has a complete solution on his blog for when you specify such a property from the command line.
Normally the original entries in the directory table are stored for reinstall without that you store them yourself.
So there is something "special" in your MSI, if this doesn't work. If you have a custom action which sets directory properties like INSTALLDIR, you should not use it. E.g. give them a condition "Not Installed".
I found out that the problem was due to using a wildcard for the product id, so every time a new msi was built it created a new product id.
By fixing this it seemed to resolve the problem, though I have also implemented the registry key option as it will help for upgrades where I do want to change the product id.
Thanks

IzPack: is possible to create one app updater?

I created one installer with IzPack. Everything works fine. Now I'm wondering, is there a good way to create one installer that will take care of update the application if this already exists?
I tested running the installer again, but he not recognize that the application is installed.
I have used IzPack for installing and updating. IzPack does not natively tie in with any packaging system so there is no way for IzPack to conclusively know if something has been installed. You might try to interact with registry or some specific flie you create at install time but that is still messy (to me anyway).
IzPack does however check if a file already exists before overwriting it so if you are running an update then an example is that you would want binaries to be updated but user configuration left alone so do something like this inside the packs element:
<packs>
<pack name="CorePack" required="yes" preselected="yes">
<description>The core of the app.</description>
<file src="bin/binaryapp" targetdir="$INSTALL_PATH/bin"
override="true">
<os family="unix" />
</file>
<file src="etc/config.conf" targetdir="/etc/appdir">
<os family="unix" />
</file>
</pack>
</packs>
You see that the binary has override="true" where the config does not (by default override=false). Binary gets updated, config does not.
Jeff
CheckedHelloPanel will do your job, at least for windows. It writes something to the registry and checks this if you try to reinstall.