5

We are trying to deploy an update to our product which contains an updated dll. This dll also has a version number so normally the installer should be able to see this and replace the old dll.

Windows installer only cares about the first three numbers when checking version number. However in this case the updated version number looks the same save for the fourth number. So for example if the previous one hade 1.0.0.12 this has 1.0.0.20 hence the installer see them as the same version and does not replace the file. I have no control over the version numbering in this case and since we include a lot of dlls this could happen again in the future.

How would one go about making the installer replace the file no matter if the version number is the same?

After searching for different solutions I have tried to tell the installer to remove the file during the install process. I do not want to remove all files if not necessary. So far I have tried the solution as showed in the included code snippet. The removefile element is new in this version of the installer.

<Component Id="SomeComponent" Win64="yes" Guid="*">
<File Id="SomeFile" KeyPath="yes" Source="$(var.app.TargetDir)\some.dll" />
<RemoveFile Id="RemoveSomeFile" Name="some.dll" On="install"/>
</Component>

The result i expect is for the old dll to be replaced by the new dll however after install the old dll is still there and no new one.

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
oldgast
  • 75
  • 9

1 Answers1

4

Similar Answer: File of a new component isn't installed because there was an old component with the same file


Companion Files: How to use Companion Files in WiX - just a snippet (after debugging it was discovered that OP had an issue of needing to downgrade files instead of a problem with number of version digits - very common issue):

<..>

<Component Id="MyFile.exe" Feature="Main">
  <File Id="MyFile.exe" Source="MyFile.exe"></File>
</Component>

<Component Id="MyFile_2.exe" Guid="{0EBDFD64-017B-428F-BB67-3D82EA2A99AF}" Feature="Main">
  <File Source="MyFile_2.exe" CompanionFile="MyFile.exe"></File>
</Component>

<..>

One-Line Summary: In the second component we point to the first component's file so that MyFile_2.exe will install whenever MyFile.exe is installed - regardless of versioning issues.


Older answer below left in for reference and the WiX source that can be used for testing.


MSI Version: Windows installer only cares about the first three numbers when checking version number.

File Version vs ProductVersion: The above statement is generally correct, but to the best of my knowledge (and based on a quick smoke test), this 3-digit restriction only applies to the MSI's ProductVersion (the version of the MSI itself), and not to actual file version numbers.

File versions are respected in 4 digits, as opposed to the 3 digit limit for the MSI's ProductVersion (the version for the MSI itself). Please run a test yourself to be sure. Sample WiX markup to do so below.


REINSTALLMODE: The file-overwrite modifier mechanism REINSTALLMODE can be used to force overwrite files regardless of version. This mechanism must not be used since it can cause a number of problems: unnecessary reboot prompts, downgrading of system shared files, cause some files to be upgraded and others not (old and new packages installed out of sequence), in earlier versions of Windows crashes as protected files are attempted downgraded, etc...


WiX Mockup Test Source: I'll dump a simple test WiX source here to help you test this quickly (on different OS versions for example, I tested on Windows 10):

Incidentally, due to some inherent design characteristics of this sample, it will also illustrate that major upgrades fail when you only bump up the last digit of the 4-digit version number, but file overwrites will work. When you install version 2, you will find two product entries in Add / Remove Programs. This is expected based on the design of the sample. Just uninstall both.

<?define MyVersion = "1.0.0.0" ?>
<?define MyReleasePath = "$(sys.SOURCEFILEDIR)_Files\$(var.MyVersion)\" ?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

  <Product Id="*" Name="FileVersioning" Language="1033" Version="$(var.MyVersion)"
           Manufacturer="FileVersioning" UpgradeCode="{4864AA4A-EA1D-4367-8427-85D296B0A2A6}">
    
    <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
    <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
    
    <MediaTemplate EmbedCab="yes" />
    <Feature Id="Main" Title="FileVersioning" Level="1" />
    
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLFOLDER" Name="FileVersioning">
          <Component Feature="Main">
            <File Source="$(var.MyReleasePath)MyTestFile.exe"></File>
          </Component>
        </Directory>
      </Directory>
    </Directory>
  </Product>

</Wix>

Usage:

  1. Create WiX project, replace template content with above markup.
  2. Make a sub-folder in WiX project folder called _Files and two further sub folders under there with two versions of the same file as illustrated below.
  • Quick Way: In Visual Studio, right click the WiX project and select Open Folder in File Explorer to get to the WiX project folder quickly.
  • Now paste in two folders or create them.
  • You can open the EXE in Visual Studio to "hack" the version number so you use the same EXE or DLL in both folders with different version numbers. See section below for information.
  1. Change MyVersion define to the version number you want to build. For example: <?define MyVersion = "23.4.5.2" ?>. This also affects where the sample expects the source file to be located on disk.
  2. Update the file name in the File element to match the name of your versioned file (<File Source="$(var.MyReleasePath)MyTestFile.exe"></File>).
  3. Compile setup, install it, inspect version number for installed file.
  4. Change the WiX version and compile the next setup (<?define MyVersion = "23.4.5.3" ?>).
  5. Install on top of existing install. Check that the new version of the file has been installed.

Folder structure for versioned files (create inside main project folder):

_Files
   23.4.5.2\MyTestFile.exe
   23.4.5.3\MyTestFile.exe

Open EXE as Resource: In Visual Studio try this:

  1. File => Open => File
  2. Browse for a versioned file (EXE, DLL, etc...)
  3. Click versioned file once (and only once)
  4. Click the down arrow for the Open button => Open With...
  5. Select Resource Editor and open file.
  6. Locate Version section, open and double click entry.
  7. Change version numbers, save new file version (not on top of existing).

Links:

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • Thank you for the extensive answer! I really appreciate it. I will try this immediately. – oldgast Feb 19 '19 at 14:03
  • No problem. It is overkill the whole answer, but I just wanted to persist that WiX sample online so I can find it again myself. I'll add a note on REINSTALLMODE as well. – Stein Åsmul Feb 19 '19 at 14:06
  • Tested your example. Again great guide! This works as expected for me. And as you say it seems that it is actually productversion that only checks for three of the numbers. However one thing that differs between your example and mine is that your source file between the two versions is located in different folders. Do you think that the installer will see them as different files or does it not "care" about the source location? – oldgast Feb 19 '19 at 14:30
  • They are in different folders because they are the same file in different versions (so I can use the same file name). If you use different file names then there is no file overwrite behavior that is relevant since no files are overwritten / upgraded? (just installed). – Stein Åsmul Feb 19 '19 at 14:43
  • Ok thank you for the help! I will test this out further and come back with my findings. There may be something else going on here that I'm missing. – oldgast Feb 19 '19 at 15:04
  • Ok so this is really embarassing. Appearantly the new version of the dll I wanted to include actually has a lower version number. I may have been fooled by the fact that it was a newer version of the dll but I should have realized that when I actually checked the number. Instead I confused myself for a long time. However I can confirm that the installer does the right thing and actually choosing the file with the higher version number. So now I will go ahead and figure out a solution to replace the file even though the version number may be lower. – oldgast Feb 19 '19 at 16:55
  • Thanks anyway for the great help! Even though I messed up in my thinking you lead me to the cause of the problem. Hopefully it might help someone else in the future. :) – oldgast Feb 19 '19 at 16:59
  • Not to worry, I wanted to add that source to find myself if I need it. Downgrading files is not good, in fact it is terrible. You can hack a new version for it as I describe above, would that work for you? That might actually work without incident, though it is the kind of advice you don't really want to dish out as the first option - hacky. You should investigate the concept of "[**companion file**](https://stackoverflow.com/a/1434514/129130)". I am not too happy about that answer, but it should get you going at least. – Stein Åsmul Feb 19 '19 at 19:52
  • Added a section on top on how to use [**Companion Files**](https://learn.microsoft.com/en-us/windows/desktop/Msi/companion-files) with WiX. – Stein Åsmul Feb 19 '19 at 20:17
  • Reading you links it seems that marking the file as a companion file might be the cleanest approach. The remove file approach seems a bit clunky if the install would fail. Hacking file version seems a bit risky to me if another file would expect a certain version but maybe that is not very common. – oldgast Feb 20 '19 at 06:16
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/188757/discussion-between-oldgast-and-stein-asmul). – oldgast Feb 20 '19 at 14:00
  • @SteinÅsmul Is there any way to get the version programmatically from an `*.exe` as opposed to having to manually replace the `MyVersion` you have defined? For C# applications, you can get the version using `` (in the `*.wixproj` file), but this doesn't work for C++ apps and actually throws an error. – Code Doggo Feb 20 '20 at 19:43
  • Not sure what exact requirements are, but how about [using the VBScript and the Scripting runtime](https://github.com/glytzhkof/all/blob/master/GetVCRuntimeFileVersion.vbs)? – Stein Åsmul Feb 20 '20 at 20:05