Forcing an upgrade of a file that is modified during its initial installation
Asked Answered
W

3

15

I'm working on the upgrade feature for my WiX-based installer.

As part of the instalation, we are installing a web.config file and then using a custom action to update the connection strings inside the file.

But this causes a problem when we run our upgrade. We would like to have the RemoveExistingProducts scheduled for after InstallFinalize since this is most efficient in terms of not removing and reinstalling files that have not changed. But this leaves the original web.config file in place at the time when Windows Installer is trying to determine whether it should update it or not. Since it's last modified date is more recent than its creation date, Windows Installer decides not to update it (see versioning rules that Windows Installer uses). But we need it to be updated.

One obvious solution is to change the scheduling of RemoveExistingProducts to after InstallValidate - but this is inefficient, and also, I don't think it would give us the opportunity to migrate settings from existing files, should we need to do that.

Any other ideas?

Worldweary answered 16/9, 2009 at 10:52 Comment(0)
P
19

Newer answers: 1) Companion files, 2) file version hack using Visual Studio, 3) moving the file to another installation path, 4) variations of REINSTALLMODE, 5) "version lying", etc... All kind of options, most of which are not ideal:

Below is an older answer. I don't think option 2 works properly anymore:


There are many ways - none are ideal.

1: You can use a companion file to force update of the file in question. Provided the companion file specified always gets updated, this may be the way to go. Essentially this means that you link the non-versioned file to the version update logic of its companion file (files are updated together). I have never used this in WIX, but I think it's as easy as adding the CompanionFile attribute to a File element and point to the ID of the file you want to "version follow". Inside the MSI file it will look something like this:

enter image description here

2: You can use a custom action to delete the file before file costing (or better yet, rename it to a backup format). The problem is that if the setup fails the file will be missing. If you rename the file instead of deleting you can put it back in case the setup fails via a rollback custom action. Sometimes I use the RemoveFile table to remove files on install, but depending on the sequencing specified in InstallExecuteSequence this may not work (deletion must happen before msi does file costing).

3: Then there is the sledgehammer approach: set REINSTALLMODE = amus to force overwrite all files regardless of version. I shouldn't even mention this since it is horribly dangerous (you can end up overwriting system files, or on newer Windows versions trigger a nasty runtime error as files are protected). Use it only for dev testing, and don't think it is a quick fix. It causes more problems than it solves.

As a variation, an acceptable approach may be to set the REINSTALLMODE to emus (replace older and same version files). This can help if you don't want to increment the version numbers but keep rebuilding your binaries - as is the case in a lot of .NET. My guess is this will cause a whole new range of problems though - most significantly binary different but version identical files in the wild if you use it for public releases - a deployment smell if ever there was one. As a QA/DEV only approach it could work though. But seriously, why bother? Just auto-increment the build version of the binaries and the problem is solved reliably.


Links:

Portland answered 16/9, 2009 at 17:49 Comment(9)
wix.mindcapers.com/wiki/Companion_File for a quick sample of how to implement the companion file approach in WIX.Nashville
The Companion file approach looks like it might be the way to go. Thanks for the link. Thanks also for the warning about REINSTALLMODE: I had read about that, and was considering it - no longer!Worldweary
Darn, wix.mindcapers.com/wiki/Companion_File was taken offline :(Shanaeshanahan
I believe Wix has made it easy to use Companion files. I think it is just an attribute you set in the file or component tag. See the image added above for an illustration of how it is implemented inside a regular MSI file.Nashville
@Glytzhkof How is REINSTALLMODE going to overwrite system files if you're not installing any system files?Caress
@azhrei: System files can be included in merge modules included by the MSI. You may also end up overwriting changed data files that you have installed previously.Nashville
@azhrei: At the very least, never set REINSTALLMODE to amus in the Property table, only use it on the command line. Still don't recommend it even if there are no system files though. Bad habit.Nashville
I recommend using companion files only when the accompanying file's life cycle is actually stapled to the versioned file, such as *.config files for .net assemblies. In cases where the file is independent, version lying is the best approach as it doesn't introduce any dependencies. For all accounts it is equivalent to an AlwaysOverwrite flag, except that flag is not necessary because there is version lying. If you're using "REINSTALLMODE=amus" then I strongly recommend you switch to using SFX archives. That's like building a spaceship to get to the other side of the road.Unlawful
As you see in Michael Urman's answer "version lying" as you call it can cause patching problems. I have never tested it myself, but it sounds logical and I assume Urman has tested it several times since he is very involved with the technical details of MSI.Nashville
E
1

Only iffy ones. You could remove the specific file early with a custom action, but be sure to condition this right! Or you could specify a version for the file so upgrade rules will treat it like replacing a non-versioned file with a versioned one, but then patches can get antsy about having the wrong version of this file.

Elemi answered 16/9, 2009 at 14:51 Comment(2)
Are you implying that companion files cause problems for patches? If so, can it help to include only whole files?Nashville
The patching problems arise if you do binary differences and the base lied about the version. So including whole files can indeed help, but it's still not perfect. I believe the companion file story is much better behaved.Elemi
B
0

Don't use a custom action to update your config file is the other obvious idea. Instead get WIX to do the update via the XML extensions. E.g.

<Component Id="web.config" Guid="f12ff575-ad5f-47bc-a5c9-40b1e3a7f9f5" >
    <File Source="$(var.SrcPath)\web.config.config" KeyPath="yes" />

    <util:XmlConfig Id="AppSqlInstanceName"
                    File="[#web.config]"
                    Action="create"
                    ElementPath="//configuration/connectionStrings/add[\[]@name='YourStringKey'[\]]"
                    Name="connectionString"
                    Node="value"
                    Value="metadata=res://*/YourModel.csdl|res://*/YourModel.ssdl|res://*/YourModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=[SQLSERVERANDINSTANCE];initial catalog=DatabaseName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;"
                    On="install"/>
</Component>

This is using a [SQLSERVERANDINSTANCE] variable which needs to be setup before hand.

Buine answered 19/7, 2018 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.