How do I stop removal of files during uninstallation using Wix - 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

Related

Patch (minor upgrade) creation issues with MSM (merge modules)

I am facing issues with patches (minor upgrade) installation (updates) with MSM (merge modules).
I am creating MSI (test.msi) with texst.wxs. And inside text.wxs referring to app.msm file (there is a folder app, which contains so many folders and files. And harvesting this folder and making app.msm file)
Below are steps for making app.msm file.
heat dir "app" -gg -sfrag -template:module -srd -ke -var var.source -out app.wxs
candle -dsource=app app.wxs
light app.wixobj
Below is snippet of test.wxs file
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
....
....
<Directory Id='Config' Name='Config'>
<Component Id='APP_CLIENT' Guid='*'>
<Component Id='Manual' Guid='*'>
<File Id='Manual' Name='Manual.pdf' DiskId='1' Source='Resources/Manual.pdf'
KeyPath='yes'>
<Shortcut Id="startmenuManual" Directory="ProgramMenuDir"
Name="Instruction Manual" Advertise="yes" />
</File>
</Component>
</Directory>
<Directory Id='exmp_REPO' Name='!(loc.Merge_FolderTitle)'>
<Merge Id="LocalRepository" Language="1033" SourceFile="app.msm" DiskId="1"/>
<Component Id='exmp_REPOSITORY' Guid='*'>
<CreateFolder/>
<RemoveFolder Id='exmp_REPO' On='uninstall' />
</Component>
</Directory>
....
<Feature Id='Complete' Display='expand' Level='1' ConfigurableDirectory='MYAPPPATH'>
<ComponentRef Id='Manual'/>
<ComponentRef Id='App_CLIENT'/>
<ComponentRef Id='exmp_REPOSITORY'/>
...
...
I am able to make major upgrade with my test.wxs by using app.msm (merge module). But not able to make patch with successful installation. Patch install (update) is reflecting in version change in the "Programs and Features" and showing in "View Installed updates". The manual changes also are reflecting with patch update. But whatever the changes in "app" (which are created app.msm and referred in test.wxs) folder are not reflecting.
I have used 2 approaches for making patch, which are mentioend in below urls
1) http://wixtoolset.org/documentation/manual/v3/patching/patch_building.html
2) http://wixtoolset.org/documentation/manual/v3/patching/wix_patching.html
Please help in this regards.
First, I would advise to find out, whether the built patch contains the correct files or not. If not, you have a build problem, that the msm is not updated. If yes, you have most likely a problem with the content of the msm which may be not consistent with it's predecessor (especially GUIDs, table primary keys, etc.).
You can find out and see the content of the patch without installing with tools like Orca and Insted which you can search and download.
Second, using merge modules is highly complicating things, especially for patches, and of limited usefulness, if they are your own and you use them only once. Msms are primarily made for situations, where you need the .msm at least for 2 different MSI packages. I have seen a handfull of problems using merge modules in patches with other tools, BTW. I have no special experience here with WiX+patches+MSMs, but, it's as I said.
Last, but not least, you will have to choose, if you really want to keep this complexity in the future. As I remember, there are other possibilities in WiX to modularize / encapsulate parts of your software.
You can check the versions of files in merge modules and MSI files by opening them with Orca and looking in the File table. Or open the MSI file with Orca and then Transform=>View patch to see changes.
It may be obvious, but a binary versioned file will be replaced by a file with a higher file version. I mention because there is a belief out there that somehow "new" files replace "old" files, and that's wrong. Versions matter.
Generally you need to install a patch with an msiexec command that specifies REINSTALL=ALL REINSTALLMODE=omus. Double-clicking an MSP file will not necessarily just work unless you've arranged for it to do this internally with a custom action that sets them when PATCH is set.
The patch will not work if you break component rules. A common mistake is to remove a component during a patch, and that will result in an "advertised" update that doesn't actually update anything. In a verbose log look for SELMGR entries and text about removal of components is not supported. Setting the MSIENFORCEUPGRADECOMPONENTRULES property to 1 will fail the patch if you've done this.
If a file has no version whether it's overwritten depends on the replacement rules here, and there's some difference if the file is hashed or not:
https://msdn.microsoft.com/en-us/library/aa370531(v=vs.85).aspx
Also: how do you know the patch isn't working? If you have no file versions then you can't know if a file has been replaced unless you look very carefully. You cannot trust the dates because Windows changes timestamps when a file is installed. You really need to build binary files with file versions because everything like patches, hotfixes, service packs etc will use them to replace binary files. Otherwise for data files use file hashing.
I see several potential problems here, maybe even in addition to the other answers:
when you heat up files for your merge modules -gg autogenerates new component guids. This will not work with patches, since it'll basically add a bunch of new components (new guids each time!!). Also, you'll remove components this way, which is something you shouldn't do and which cannot be done easily, unless you still include the original merge module. And then you'll end up with path problems.
The tutorial for wix patching uses wixpdb files for diffing the original and the updated installer. With wixpdb files, merge modules will not be patched, irrespective of whether files changed in them or not. You will need to do administrative installations and then diff on the msi itself. You'll still have problem #1.
your wxs snippet is bad. At least the xml element is never correctly closed. Your Feature also has a MergeRef somewhere?
Some tips:
you can view what your patches do with a program called Orca. Open the original msi, then just drag your msp patch file on top of it.
rather don't use merge modules, they complicate things. You can also use heat to generate a fragment which you then simply include into your wix project.
use the wix patching approach (Patch element, not the PatchCreation element). It's easier, but you have the same control
don't autogenerate guids if you plan to update those autogenerated components with a patch. It won't be a problem with major upgrades :)
Just one important issue of a number of potential reasons while files are not updated correctly: You write, in your .msm is a high number of unversioned files, like .xml, etc.
Important rule:
EVERY unversioned file which is changed on the PC AFTER the first MSI install not by the MSI engine itself (e.g. you edited a config.xml file or so), will be normally NEVER updated by MSI again, not by patch and not by Major Upgrade. (With normally I mean, you have to take special actions, like uninstalling or especially specifying those files as socalled companion files).

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

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>

Config files for GAC assemblies using Wix

I know this has been asked a few times in the past. And I have read all the responses and answers and none of them seem appropriate.
I've tried putting the .config in the same component and in a different component.
I've tried CompanionFile in the same component and in a different component.
I've tried CopyFile.
I've tried a Custom Action.
The component needs to be in the GAC because it is a general logging dll used by many different subsystems (services, websites, etc). But it is configured the same for all systems.
So for now I'm installing the file to a SDK directory and telling the user to copy the file.
The ONLY thing that works is copying the file manually and saying yes to "you need admin perms to do this".
<File Id="SDK.Logging.dll.config"
Source="$(var.LOGGER_DIR)\SDK.Logging.dll.config"
Vital="yes">
</File>
<Property Id="XCOPY">xcopy.exe</Property>
<CustomAction Id="Copy.SDK.Logging.dll.config"
Property="XCOPY"
ExeCommand='"[INSTALLLOCATION]SDK.Logging.dll.config" "[GAC.SDK.Logging.Dir]"' />

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.

Can a .msi file install itself (presumably via a Custom Action)?

I wand to construct an MSI which, in its installation process, will deploy itself along with its contained Files/Components, to the TargetDir.
So MyApp.msi contains MyApp.exe and MyAppBootstrapperEmpty.exe (with no resources) in its File Table.
The user launches a MyAppBootstrapperPackaged.exe (containing MyApp.msi as a resource, obtained from the internet somewhere, or email or otherwise). MyAppBootStrapperPackaged.exe extracts MyApp.msi to a temp folder and executes it via msiexec.exe.
After the msiexec.exe process completes, I want MyApp.msi, MyBootstrapperEmpty.exe (AND MyApp.exe in %ProgramFiles%\MyApp folder so MyApp.exe can be assured access to MyApp.msi when it runs (for creating the below-mentioned packaged content).
MyAppBootstrapper*.exe could try and copy MyApp.msi to %ProgramFiles%\MyApp folder, but would need elevation to do so, and would not allow for its removal via Windows Installer uninstall process (from Add/Remove Programs or otherwise), which should be preserved.
Obviously (I think it's obvious - am I wrong?) I can't include the MSI as a file in my Media/CAB (chicken and egg scenario), so I believe it would have to be done via a Custom Action before the install process, adding the original MSI to the MSI DB's Media/CAB and the appropriate entry in the File table on the fly. Can this be done and if so how?
Think of a content distribution model where content files are only ever to be distributed together with the App. Content is produced by the end user via the App at run time, and packaged into a distributable EXE which includes both the App and the content.
MyApp's installer must remain an MSI, but may be executed by a Bootstrapper EXE. The installed MyApp.exe must have access to both MyApp.msi and EXE is to be "assembled" at runtime by the App from a base (empty) MyAppBootstrapper.exe, which is also installed by the MSI, and the content created by the end-user. The EXE's resource MSI must be the same as that used to install the App which is doing the runtime packaging.
WIX is not to be installed with MyApp.
There can be no network dependencies at run-/packaging- time (i.e. can't do the packaging via a Webservice - must be done locally).
I am familiar with (and using) Custom Actions (managed and unmanaged, via DTF and otherwise).
Add an uncompressed medium to your wxs like this:
<Media Id='2'/>
And then create a component with a File element like this:
<File Source='/path/to/myinstaller.msi' Compressed='no' DiskId='2' />
This will make the installer look for a file called "myinstaller.msi" on the installation medium, in the same folder as the msi that is being installed. The source path above should point to a dummy file, it is only there to appease wix.
Edit: The following sample test.wxs demonstrates that it works. It produces a test.msi file which installs itself to c:\program files\test. Note that you need to put a dummy test.msi file in the same folder as text.wxs to appease wix.
<?xml version='1.0' encoding='utf-8'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product
Name='ProductName'
Id='*'
Language='1033'
Version='0.0.1'
Manufacturer='ManufacturerName' >
<Package
Keywords='Installer'
Description='Installer which installs itself'
Manufacturer='ManufactererName'
InstallerVersion='100'
Languages='1033'
Compressed='yes'
SummaryCodepage='1252'/>
<Media Id='1' Cabinet='test.cab' EmbedCab='yes'/>
<Media Id='2' />
<Directory Id='TARGETDIR' Name="SourceDir">
<Directory Id='ProgramFilesFolder'>
<Directory Id='TestFolder' Name='Test' >
<Component Id="InstallMyself">
<File Source="./test.msi" Compressed="no" DiskId="2" />
</Component>
</Directory>
</Directory>
</Directory>
<Feature
Id='Complete'
Display='expand'
Level='1'
Title='Copy msi file to program files folder'
Description='Test'>
<ComponentRef Id="InstallMyself" />
</Feature>
</Product>
</Wix>
Having one .MSI package launch another .MSI package from "within" itself is called a nested install, and it's bad juju (see Rule 20). Windows Installer has some global data that it uses to manage the current install, and it doesn't handle well multiple installs at the same time. For the same reason, if you start one install and then try to start another while the first is still in progress, you'll usually see a pop-up to the effect of "another install in progress, please wait until it's done".
You can have a program, usually called a bootstrapper (I think that's what you're referring to) which is itself not an install package, but which contains an install package (such as an .MSI or an .EXE) as a resource, possibly compressed. The action of the bootstrapper program is to extract/expand the resource to a file, commonly in a %TEMP% directory, then either launch the extracted .EXE or run MSIEXEC on the extracted .MSI. The bootstrapper can contain multiple resources and extract+install them one by one, if you need to install prerequisites before the main package. Or you can ship multiple packages as separate files, and have the bootstrapper execute/install them directly from the distribution media one by one, or copy them down to the target machine and run the series of install from there, or...
WiX itself does not get installed, no. It's a tool with which .MSI packages can be built. The WiX project has on its wishlist a generic bootstrapper program, but it hasn't been implemented yet. There are other bootstrappers available, e.g. this one.
You won't need a custom action -- in fact, since the bootstrapper isn't itself a Windows Installer installation package, "custom action" has no meaning to it. And, if you're familiar enough with CAs to know about managed/unmanaged/DTF, then you know enough to avoid custom actions whenever you can. (grin)
I think it's much easier for your bootstrapper to extract MSI file to some predefined location rather than to the temp folder. For example, to C:\Documents and Settings\All Users\Application Data\My Company\My Product Install Cache. After installation finishes bootstrapper would leave MSI file sitting there. If at some stage user decides to reinstall your product Windows Installer will be able to locate source MSI file.
Also, add path to this file to RemoveFile table so that it gets deleted on uninstall. You can use RemoveFile element in WiX for that.
So if I understand, then I think I would have the app create a transform (MST) that has the content files and apply that to the base MSI. I'm still not convinced that I understand though. :)
I'd configure the MSI cache path to a known location.
Then at runtime if you need to "edit" the MSI use VBScript or similar.
But still, I ask WHY!?!
I am also working on a way to deploy multiple MSI files. I have a bootstrapper.exe program that bundles the MSI files and runs them one at a time. This solves my problem for most cases.
The case it does not solve is GPO (Global Policy Object) distribution of the install. GPO requires a dot-msi file to run an install.
To do this here's what I did which almost solved the problem (but not quite). I put the dot-msi files in the file table of an installer and put my bootstrapper in the binary table and run it from a custom action inserted after InstallFinalize in the InstallExecuteSequence. Of course the bootstrapper won't be able to run other MSI's because the top level MSI holds the _MSIExecute mutex.
It was pretty easy to get a little further. I made the bootstrapper return control to the top level installer and continute. And then I added a WaitForSingleObject call to wait for the top level install to finish, and the bootstrapper can then continue to finish the install.
My problem is that the GPO installation happens at boot time and the top level install completes before the sub installers are done and GPO reboots the machine.
The toplevel install also returns a success status when the install may actually fail later on.
I'm still looking for a way to block the top level install from completing until after the bootstrapper completes.