Custom Table to be included in Patch msp file - wix

We have a CustomTable that we add to our msi when it is created. This custom table contains some binary data (xml files) that our deployment software reads when the msi is being uploaded to our deployment server.
We now have the requirement to support deployment of msp files. This means that should the user upload an msp file to our deployment server, our software should still be able to read the binary data in our CustomTable. However I've been unable to find a way to ensure that the msp file we create contains the same CustomTable.
I know that the msp contains the updated xml because I've used ORCA to see the updated tables and files. Unfortunately I don't seem to be able to programatically read data from our CustomTable because it doesnt (apparently) exist within the patch. Does anyone know of a way to access a CustomTable from an msp file?
Thanks - If clarification is needed let me know!

The patch (msp) is supposed to contain the changes to the previous MSI package only. If you don't change your custom table in a newer version of your MSI package, then it won't be mentioned in the patch. And that's expected.
When the patch is applied, it changes the initial MSI package (actually, patches it) and runs the reinstall. This means if your custom action which reads the custom table is NOT explicitly scheduled not to run on reinstall, then it will run and it will find the custom table.

Ok, so finally have a solution to my problem.
Since we don't have the original msi, we can create a blank msi in a temp directory and then apply the msp on top of this using ApplyTransform. Providing we create the expected table, and fill it with dummy data (fortunately we know in advance what rows are expected within this table), the process of applying the patch on top of our dummy msi allows us to successfully query the _Storages table and access the updated stream containing the new xml. This can then be processed during our msp upload.
Not pretty but it works.

Related

Update and retain web.config file during upgrade in wix installer

What is the standard way to handle web.config files during major upgrade.I'm aware how the unversioned files are handled during upgrade,the file will not be replaced if the file has been modified by the user.
Is there a way to deal with the scenario where in there are new entries added to config file bundled with the latest installer that needs to be installed,and also retain the existing entries modified by the user during major upgrade in Wix.
The simple solution that a lot of my customers have liked is to not put user data in the web.config. Instead we use the AppSettings#file and ConnectionStrings#ConfigSource elements to specify an override file and keep the user data there. What MSI doesn't know about it won't tamper with. Now you don't have to be an MSI component rules wizard.
https://msdn.microsoft.com/en-us/library/ms228154(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/system.configuration.sectioninformation.configsource(v=vs.100).aspx
I know the question is for Wix, but just wanted to point out how much time commercial tools can save in such scenarios.
For example, using Advanced Installer you can read and load into an MSI property any XML values and then use the XML Files updater to write dynamic content in the files, at install(upgrade) time. (check the videos at the end of each article for a quicker overview)
Disclaimer: I work on the team building Advanced Installer.
Set the component to always overwrite and write a custom action to add the needed information to the config file.
The only way that seems possible is a custom action to merge the entries in the new file into the existing file, because you want data from the existing a new files. You would also need the upgrade scheduled late (after InstallExecute) so that the upgrade isn't an uninstall of the old product followed by an install of the new product.
If you are doing an upgrade (the WIX_UPGRADE_DETECTED property will be set by a MajorUpgrade element), so update the existing file, otherwise install the new one.
There might be a way to express the updates as an Xml transform, so something in the WiX util:xml tools might help do an update.

Alternative to WiX Patch

I have an MSI, which adds a registry key, installs and starts some services, installs a file and so on. Now, there is a requirement to update one file and add a new file. I know we can create a Patch by creating a difference / transform. But in my second MSI, I only want to include these 2 files (the updated one and the new one) and not the other files, probably like a HotFix. I don't want to create a Patch. I did try to create a separate MSI but with the same UpgradeCode but with a different Product ID and a different version. But this creates a new entry in Programs and Features. Also, while uninstalling this new MSI, it does rollback the new file, but it doesn't rollback the modified file (this file was originally created by the first MSI and modified by the second one). At least if it is able to rollback and restore the state during uninstallation, it would have been great. But it is not rolling back the modified file properly.Has anyone come across this scenario? If so, have you been able to find a solution without a Patch? Please help.
There are three ways to update an installed product: a patch, a major upgrade and a minor upgrade. Although you can create a new MSI that replaces some of the files in an existing product what you are actually doing is sharing them in the same way that Microsoft Dlls (for example) are shared between many different products. (Unless you use the same component Ids and share properly you are more likely to break the product instead of updating it.) This is why you see that behavior of preserving files.
The idea that the patch may contain "contain other changes also which he is not interested in" should not be an issue. You create the patch so that it contains only those changes. It will contain other changes only if you put them in the MSI file when you create the patch.
Adding files during a patch can be tricky because there are some rules involved.
The safest thing to do is a major upgrade when adding new files.
So the choces are:
A patch that contains only the required updates.
A major upgrade, which is the complete new MSI file that upgrades the product.
A minor update which again is the complete new MSI file with the same ProductCode, incremented version, only minor hotfix changes, install with a special command line that includes REINSTALL=ALL REINSTALLMODE=vomus
Only the patch can be made to include just the changes required.

How can the contents of an installed file marked Permanent="No" be preserved during an upgrade?

Installers of previous versions of our software include a Component File that was NOT marked with Permanent="Yes". Now, we wish to read the pre-upgrade contents of this file during the upgrade process, which will overwrite the file with different contents. Is there a good way to do this?
It would help if you said exactly what you were doing that would cause the file to be overwritten. Some major upgrades (is that what you're doing?) will do a complete uninstall of the product first, followed by a complete install of the newer product. If that's the situation then use a custom action sequenced before RemoveExistingProducts to back up the file somewhere so that your application can retrieve the content, or get the content you need before it's ovewritten.
If you are doing a major upgrade sequenced later (such as afterInstallExecute) or you are doing a patch then it is by no means certain that the file will be overwritten because file overwrite rules will not replace a file that has been updated since it was installed. If the application altered the file then this type of upgrade will not overwrite it:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370531(v=vs.85).aspx
Or in the case that the file is unchanged since it was installed, change the dates so it appears to be modified, as described here:
https://blogs.msdn.microsoft.com/astebner/2013/05/23/updating-the-last-modified-time-to-prevent-windows-installer-from-updating-an-unversioned-file/
It's also not clear that Permanent=yes is what you want anyway - that would glue the file to the system forever. You may be thinking of NeverOverwrite, but it's typically not required if the app changes the files, and easier to decide at upgrade time (by changing dates) instead of committing to NeverOverwrite when it's sometimes unclear what the product may need in the future.
A comment refers to retrieving the previous version of the product during the upgrade. There are a number of ways to do this:
If you know the ProductCode of the previous version, MsiGetProductInfo (and equivalents in script etc) will return product version values or strings:
https://msdn.microsoft.com/en-us/library/aa370130(v=vs.85).aspx
Or if you'd rather not hardcode the value, MsiEnumProducts passing the UpgradeCode will return a list of installed ProductCodes. This technique is most useful if you have your own bootstrapper or UI where you want to show the user the current installed version.
In a WiX major upgrade the associated property (WIX_UPGRADE_DETECTED) is a list of the ProductCodes detected (usually a list of one) so you can use that to get the version of the product being upgraded. In a small vbscript example, something like:
set installer = CreateObject("WindowsInstaller.Installer")
and:
prodversionstring = installer.productinfo(WIX_UPGRADE_DETECTED, "VersionString")
will get you close.
Assuming this file is a configuration file such as an XML file, I find this is just a tough area of Windows Installer. You ship file version 1, the end user modifies certain attributes and then you ship file version 2 to which you want to preserve those customizations.
The problem is this is a very complex merge. It works somewhat OK if you only care about 1-2 attributes but if the answer is I need to preserve all of it then you are stuck between losing all the customizations or not getting the changes from version 2 of the file.
You could write extensive custom actions to do all this during the installer but I propose there is a better way: Have 2 files.
1 file that is owned by the installer and can always be safely overwritten and 1 file that is owned by the application that overrides are stored in. Think of it like a transformation file. The installer doesn't know about this file so it never overwrites or deletes it. (The very definition of user data from an MSI perspective.)
For example the .NET framework Web.Config schema AppSettings element has a file attribute that was designed to support this nicely.
Specifies a relative path to an external file containing custom
application configuration settings. The specified file contains the
same kind of settings that are specified in the , , and
elements and uses the same key/value pair format as those
elements. The path specified is relative to the main configuration
file. For a Windows Forms application, this would be the binary folder
(such as /bin/debug), not the location of the application
configuration file. For Web Forms applications, the path is relative
to the application root, where the web.config file is located.
Note that the runtime ignores the attribute if the specified file can
not be found.

Remove or rename files during minor update(wix 3.9 patch)

We’re generating setups automatically every week, in order to fix bugs or introduce new features to our product.
All the components are being harvest automatically in the Wix Library(ies) pre build step(s).
eg:
"%WIX%bin\Heat.exe" project "%SolutionDir%projectNameXXX.Web\projectNameXXX.Web.csproj" -configuration %FlavorToBuild% -directoryid dirBE9FDAE56D974104BBF8070FB6CC7F69 -platform AnyCPU -pog Content -projectname projectNameXXX.Web -ag -sfrag -out "%ProjectDir%projectNameXXX.Web.wxs"
So, there is a component with a “*” Guid for every file we’re deploying.
We’ve automatized also the patch creation between any previous version of our setup (let’s say V0) and the current version (V1). The patch gets created, and is being deployed, as long as no file is being removed(or renamed) by V1. We don’t mind if the files from V0 don’t get deleted, as long as updated files and new files get deployed.
So far I’ve done dozens of tests, with different parameters for example:
adding –sfdvital on candle in order force the files not to be vital, but I finally figured out that the problem comes from the components, not the files…;
another significant test was setting hard coded Guids on 3 Components in V0, that I remove in the V1 setup. The generated patch gets installed (the to be deleted files are still on the disk, all the other files updates get deployed). When the setup gets uninstalled, everything is removed except for the 3 files. Unfortunately, if the setup V1 removes the 3 files but adds 1 other file, the patch doesn’t get installed, it stops as soon as it encounters the first to be removed file.
SELMGR: ComponentId '{68FB7BC2-8D59-4CFB-88F5-9AA8CA570345}' is registered to feature 'ProductFeature', but is not present in the Component table. Removal of components from a feature is not supported!
The related topic :
Remove file during minor upgrade
is not presenting a viable solution as I cannot apply the “puncture pattern” technique, or add tags as this cannot be done automatically. Or can it?
If a user has to edit the V0 msi, get the components ids and add them to the new msi or patch, this is not a solution for us. We’re deploying over 25000 files. A major upgrade is not a solution either.
Any idea would be welcomed!
You can't delete the component, but you can matk it transient and associate it with a property with a false value so that the file is not actually on the system. The component is still there but the file will be gone. The same should work if you want to rename a file. As above, arrange for the file to be absent and add the renamed file as a new component to an existing feature.
Minor updates are really used for fixing existing resources, not adding, renaming or removing them, which is why the safest solution is a major upgrade.
We have finally managed to generate minor update patches that are successfully installed.
Here is what we have done:
We have our SetupV0.msi
In the PreBuildEvent of our wix setup project we run dark.exe on the SetupV0.msi, e.g:
"%WIX%bin\dark.exe" "%OldSetupDir%SetupV0.msi" "%OldSetupDir%SetupV0.wxs"
A wxs file gets generated.
Then we call a console app that reads all the component GUIDs and ids from the resulting wxs and, for each one of them, tries to find a match in all the wxs libraries that are in our workspace. We recover all the GUIDs and ids that don’t have a match and we generate a wxs file with empty components (that have bogus registry keys as children) and component refs. This generated wxs is already included in the setup project.
Then the build happens and a SetupV1.msi gets generated. This setup contains all the component ids and GUIDs of the V0 and possibly some new files.
Then, in the PostBuild event we create the msp.
Maybe it is not the neatest solution, (not very proud of the registry keys), we’ve tried to add empty createfolder tags, but the create folder tags made the patch uninstallable.

How to copy a folder (not a file) during installation with WiX?

I'm writing an installation code using Wix, and I need to install an entire folder to a certain location, and then copy that folder to several different locations, I could install those same files to those locations using code one by one, but that folder is about 80 Mb in size, so it would increase my MSI size (80 x 3 = 240 Mb).
One solutions I had thought of was compressing the folder into a zip file, and then use the CopyFile element to copy the file, after that, descompress the three folders, but this increases the installation time too much.
Is there a way to do this using native wix code, or is Custom Actions my only solution?
Tnks
WiX's "smart cabbing" reuses one instance of a file's stored data even if it's included multiple times in different directories. See http://robmensching.com/blog/posts/2007/6/1/quotSmart-cabbingquot-added-to-WiX-toolset. So you have duplicate authoring but without bloating the .msi.
If you want to do it the way that MSI natively provides, you need to author 3 CopyFile elements for every single file that you want duplicated.
The CopyFile element maps to the DuplicateFile table which is processed by the DuplicateFiles action. It has no concept of */ rather it requires a 1 to 1 mapping back to the File.File_ table/column. ( File#Id in WiX )
You certainly could decide that you hate this pattern and roll your own custom actions to handle the job but if you do, make sure you handle install, uninstall, repair, rollback, upgrades and so on. MSI's restrictions can be annoying but you do get a lot for 'free' (albeit not painless) if you use it.
CopyFile Element
DuplicateFile Table