A General Approach to Software Package – Using DuplicateFiles

In my last blog post I covered the most important options for propagating user settings in an MSI. These user settings can basically be registry keys or files. When one wants to distribute files to the different user profiles on a machine, a specific issue crops up, which is the reason for this post.

Let’s set the stage. If you have ever seen the dialog below when your package is repairing or self-healing for a user, you’re in the right place.


So, what’s going on here? Well, basically, Windows Installer is trying to place a file (or files) into the user’s profile and ran into a problem. It cannot find these files.

The reason why this happens is Windows Installer did not cache the file on the local machine. Whenever an MSI gets installed on a machine, Windows Installer places a version of the MSI in a local cache located at %WinDir%\Installer as a reference to use during later operations. However, this MSI is not the same as the original one, because all files get stripped out of it. So while this is fine for referencing registry keys, ini files (from the IniFile table)  and other stuff that’s all in the msi tables, as soon as you try to write a file, Windows Installer will revert back to the original install location that you ran the MSI from.

In most deployment scenario’s today, installations are done from a central network location, using LocalSystem credentials. Normal users however, do not always have access to this central location, so when the scenario above arises, the original installer is out of reach. Windows Installer will then get cranky and demand you give it that original MSI (or else..)

REMARK: just thought I’d mention this. In an AD-based environment, it is sufficient to give the Domain Computers group read access to the network location that holds installation media to allow Windows Installer to reach it. Since this is not always possible/desirable though, there is another option: DuplicateFiles

So how do we tackle this problem? To me the most consistently robust and elegant solution is to use the DuplicateFile table in the MSI. The idea behind this technique is to put all files that are to go into the user profile into a local location that’s reachable to the application users (that would probably be the application’s Program Files folder..) and to create ‘copies’ of these central files that go into the profiles.


A quick peek at MSDN teaches us the DuplicateFile table has the following fields:

FileKey: A primary key, a non-localized token, identifying a unique DuplicateFile record 

Component_: An external key to the first column of the Component table

File_: Foreign key into the File table representing the original file that is to be duplicated

DestName: Localizable name to be given to the duplicate file. If this field is blank, then the destination file is given the same name as the original file.

DestFolder: Name of a property that is the full path to where the duplicate file is to be copied


This table basically allows you to tell Windows Installer that one file in your package is actually a duplicate of another.

So step by step, the procedure for using this technique is as follows:

  1. In your package create a folder to hold the user-files (I like to call it “_user”). Make sure regular users can reach this folder.
  2. Put all the user-files in that folder (preferably in their own specific component)
  3. For each file, fill out a line in the DuplicateFile table, indicating the original userfile, the component that’s linked to it, if needed a new name for the file once it goes into the profile, and most notably, the destination (some path under [UserProfile])

The result is that next time Windows Installer wants to put those files into the profile, instead of getting annoyed when not finding the file in the cached version of the MSI, it will actually recognise the fact that it should just copy the file that it can find in the folder C:\Program Files\<Your Application>\_user to the correct path in the UserProfile, and do so obediently. Byebye annoying dialog!!


EDIT: After akki's reply to this post, I thought I'd add this to the main article: When using the DuplicateFile table, whether by editing it manually or some other IDE specific means, be sure to verify that the MSI's install sequence contains the DuplicateFiles and RemoveDuplicateFiles standard actions. Otherwise things won't work as expected.





  • I did tried using DuplicateFile table in a test msi to get a feel of how it works. But when i installed the test package, it failed to duplicate the files on to the other folder. I didnt get any error while installing too.
    Can you provide some inputs here? - akki 9 years ago
  • without actually looking at your test package (feel free to provide it somehow) it's difficult to say. Were the duplicate files going into the userprofile or just part of the 'main' installation?

    Also, does your MSI have the DuplicateFiles and RemoveDuplicateFiles actions in the main installation sequence?

    If we are talking userprofile files, did you have a component with a HKCU keypath to trigger a self-heal? - pjgeutjens 9 years ago
    • Sorry for the late reply....
      I checked out my MSI and found that indeed "DuplicateFile" custom action was missing. Thanx for pointing it out . But isn't it supposed to be created by WISE during creating installation package. - akki 9 years ago
  • That is a valid question, but I've learned to never rely on Wise (or Adminstudio for that matter) ever doing anything automatically. Also, when you edit tables manually, you usually get a warning saying that other needed changes to tables will not be done by the IDE, I guess this is one of those cases :) - pjgeutjens 9 years ago
    • Yep this could be it.....anyway thanks for sharing it and educating us.. - akki 9 years ago
  • Hi,
    just want to leave a comment about the user's app data and self repair.
    I tried the duplicate file table, which works, because of the self-repair but unfortunately even if all files are already in c program files and you delete the MSI, the msiexec requires the source files. Probably the only way around this is with MSI version 5 - mac-duff 4 months ago
This post is locked
This website uses cookies. By continuing to use this site and/or clicking the "Accept" button you are providing consent Quest Software and its affiliates do NOT sell the Personal Data you provide to us either when you register on our websites or when you do business with us. For more information about our Privacy Policy and our data protection efforts, please visit GDPR-HQ