How can I keep WIX from resetting my users settings on updates? - wix

I have a WIX installer set up for my application and it installs correctly and updates correctly except that it re-writes the default user settings (i.e. defined in properties-> settings) that are defined in my application and corresponding dll's. How can I have WIX update the application, but not update the user settings?

Whether it's ini, registry or xml the concept is simple. Only have the installer responsible for installing defaults settings. Then on first run on your application copy the default settings to the user settings one time. Now the installer will never harm user settings because it doesn't even know of their existence.

Properties -> Settings are mapped to the app.config file for your application, so you can setup the install for that particular file to NeverOverwrite, meaning updates will not overwrite your .config file.
Working example:
<Component Id="SPECTRAVIEW.WPF.MAINAPPLICATION.EXE.CONFIG" Win64="$(var.Win64)" Guid="89E2C6C0-18FB-428B-A9EE-C2FAB3418CB2" NeverOverwrite="yes">
<File Id="SPECTRAVIEW.WPF.MAINAPPLICATION.EXE.CONFIG" Name="SpectraView.WPF.MainApplication.exe.config" Source="$(var.MainApplication.TargetDir)\SpectraView.WPF.MainApplication.exe.config" KeyPath="yes" />
</Component>

Related

How do I stop removal of files during uninstallation using Wix

When uninstalling my application, I'd like to configure the Wix setup to NOT to remove few files that were added as part of the installation. It seems like the uninstaller removes all the files that were originally installed from the MSI file. How do I do that?
Here are my files which I wish to keep it forever
<Binary Id="RootCABinary" SourceFile="Assets\Certificates\RootCA.cer" />
<Binary Id="SubCABinary" SourceFile="Assets\Certificates\SubCA.cer" />
I have used WixIIsExtension.dll to install these certificates to the windows store.
Overwrite: Is it important that the file never gets overwritten? If so, add
"Never Overwrite" to your component. WiX attribute: NeverOverwrite="yes". Remember to test upgrade scenarios!
Permanent Component: As stated by Pavel, you can set a component permanent:
<Component Permanent="yes">
<File Source="License.rtf" />
</Component>
Blank GUID: Another way to do it is to set a blank component GUID. It essentially means "install and then leave alone". No repair or uninstall should be done (remember to add NeverOverwrite="yes" if the file should never be overwritten):
<Component Guid="" Feature="MainApplication">
<File Source="SubCA.cer" KeyPath="yes" />
</Component>
Read-Only Copy: I sometimes install files to a per-machine path (for example somewhere under program files) and then copy them to a per-user location (somewhere in the user-profile) on application launch, and then do operations on them that entail that the files should not be deleted. This is good in cases where you want to do something that change the files in question (they need to be writable). Then it is good to "untangle" them from deployment concerns (files will not be meddled with by installer operations at all - the installer has no knowledge of them). The original read-only copy installed to program files can be uninstalled though (no longer needed?).
Other approaches: You can also create such files using custom actions during installation (usually text files only), you can download the file in question from your web site on application launch (makes the file easy to manage and update / replace? Vulnerable to connection problems - firewalls, etc...) and the application can create the file using "internal defaults" in the main executable on launch. And there are no doubt further approaches that I can't recall.
Put your binaries in a separate WiX component and make it permanent. Have a look at this thread as well

How to include inherited permissions when specifying permissions for a file installed by Wix / Windows Installer?

The Wix source code that I feed to the Wix compiler to build an MSI package for my application, contains the following PermissionEx directive, part of a file component which Windows Installer should install with additional (to those that should be inherited by default) permissions:
<PermissionEx Sddl="D:AR(A;;FW;;;BU)" />
As you can surmise, I intend to install the file with inherited permissions ("AR") included in its ACL and on top of that allow members of the Built-in Users group ("BU") to be allowed ("A") to write to the file ("FW").
The code above does not have the desired effect -- the file is installed, but only that single explicit ACE is listed, none of the ACEs that are supposed to be inherited from parent folder.
In contrast, if I subsequently remove all permissions from the file and run cacls file /S:D:AR(A;;FW;;;BU), i.e. specify exactly the same SDDL string, it does work as intended -- the permissions from parent are inherited and form part of the ACL, together with the explicit non-inherited ACE.
I am using Wix 3.11.1.2318 and the Windows Installer version is 5.0.16299.611, all running on Windows 10 Enterprise 64-bit. Orca tells me the MsiLockPermissionsEx table embedded in my built MSI file is populated with the intended SDDL record. So why is the file created without inheriting permissions from its containing folder?
I tried to use "AI" in place of "AR", and both strings together, but none of it had any effect either.
Is this some known limitation or a quirk with Windows Installer? I know that people were talking a while back how the old LockPermissions table (the one specified for Windows Installer versions earlier than 5) was inadequate in this specific regard -- inherited permissions, namely -- but they also said Microsoft was out to address this very issue with the new table feature.
Otherwise what am I doing wrong?
Given your knowledge in this field, you probably have already tried this. It would also be much better to eliminate the need for permissioning, but two snippets for you - notice the Append attribute:
Create a WiX project in Visual Studio. Add the Util namespace to the WiX element:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
In Visual Studio project, right click References and add reference to "%ProgramFiles(x86)%\WiX Toolset v3.11\bin\WixUtilExtension.dll".
Permission Folder:
<Component Feature="ProductFeature" Id="Test.exe" Guid="PUT-GUID-HERE">
<File Source="C:\Test.exe" />
<CreateFolder>
<util:PermissionEx User="Power Users" GenericWrite="yes" />
</CreateFolder>
</Component>
Permission File:
<Component>
<File Source="C:\Test2.exe">
<util:PermissionEx Append="yes" User="Users" GenericWrite="yes" />
</File>
</Component>
Take a look at WiX's custom PermissionEx in the Util extension.
http://wixtoolset.org/documentation/manual/v3/xsd/util/permissionex.html

How can I conditionally overwrite file during WIX install?

I have two work modes in my installer:
use config files left from previous installation
delete all existing configs and put default configs instead
The mode is determined by the checkbox in the WPF UI of the installer. If second mode is selected, then CustomAction is run, which manually deletes the configs folder from disk:
<InstallExecuteSequence>
<Custom Action="RemoveConfigsFolder" After="RemoveFolders" Overridable="yes">NOT Installed AND DELETESETTINGS=1</Custom>
</InstallExecuteSequence>
I'm using NeverOverwrite attribute:
<ComponentGroup Id="Configs" Directory="INSTALLDIR" >
<Component Id="Configs" Permanent="yes" NeverOverwrite="yes">
<File Id="main.config" Name="main.config" Source=".\Configs\main.config" KeyPath="yes" />
</Component>
</ComponentGroup>
The first mode works fine in this case, but when I try to use second mode it fails and all configs are just deleted and never created again during the installation.
During my research of the issue, I think I've found the reason why this happens: https://community.flexerasoftware.com/showthread.php?96157-The-truth-the-whole-truth-about-quot-Never-overwrite-quot-and-quot-Permanent-quot-files&p=156826#post156826
Actually this is a Windows Installer issue. If you log the uninstall
you will notice that very early in the installation the Installer
decides that the component containing this file will not be installed
because it is marked "Never Overwrite" and a copy of this file already
exists on the target machine. The uninstall happens after that which
removes the existing file. This is because the Installer decides this
when the "CostFinalize" action is launched. This action HAS to be run
before the "RemoveFiles" action.
But how do I fix it?
The problem with settings such as Never Overwrite or Permanent is they look like build settings, but they are not really - they stick to the system attached to the component id. So resetting in the project won't help because it's associated with that id. It's also not clear why setting Never Overwrite might have been a solution to some problem, because by definition patches and overwrite upgrades won't overwrite it, but overwriting it is a requirement of your setup.
Even if you had not set Never Overwrite the Windows Installer rules would not overwrite the file if it was modified after install. So if you had installed it, then it was altered, and then you did an upgrade, the file would not be overwritten (which is another reason why Never Overwrite does not seem needed).
Another issue is that your custom action RemoveConfigsFolder is not marked with an Execute enumeration value, therefore it is immediate, therefore it does not run elevated, therefore it might simply be failing, so without seeing the code it's impossible to say if reports an issue if it can't do the remove. It's also not possible to determine if it explicitly specifies the full path to the folder correctly. So the most likely quick fix to this issue is to mark the custom action as execute deferred, and the DELETESETTINGS value will need to be passed in via CustomActionData.
My initial thought is to remove the 'Never Overwrite' property. Then create a component condition that checks if the file exists. My thought is that your custom action has the condition to correctly remove the config files. If the files do not exist then the components will be selected for install.

WiX Installer removes config file values on repair

I have created an installer which copies a config.ini and asks the user for values which are then inserted into the ini file. This works fine during a fresh install and major/minor upgrades.
<Component Id="ConfigIni" Guid="GUID-GOES-HERE" DiskId="1">
<File Id="ConfigIniFile"
Name="config.ini"
Source="../../artefacts/etc/template-config.ini"
KeyPath="yes"/>
<IniFile Id="ValueOne"
Action="addLine"
Directory="ETC"
Section="sectionone"
Name="config.ini"
Key="valueone"
Value="[VALUEONEPROPERTY]" />
<IniFile Id="ValueTwo"
Action="addLine"
Directory="ETC"
Section="sectiontwo"
Name="config.ini"
Key="valuetwo"
Value="[VALUETWOPROPERTY]" />
</Component>
However, if a user tries to install the same version of the product which is already installed, the installer enters repair mode. I'm not sure how repair mode works, but in the case of the config.ini file, it seems to be deleting the one with populated values, copying it again, and because it's a repair it's not got any user values to populate the config.ini file with, so the file is blank.
Is there any way of getting the installer to ignore this file on repair, or get the original user values?
The basic problem is the property values not being preserved. There is no magic that automatically saves the values of properties between an install and a repair (or adding new features etc). The problem is not that the file is being replaced because Windows will not replace files that have been modified with user data.
In WiX, use the "remember property" pattern to save the values of properties so that they are restored in these maintenance cases.

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.