I need to extract the files from an MSI into a folder, but change the directory structure of the files, all from within a C# application (ie: not by doing an admin install, or any other install of the MSI). Conceptually, I want to "unzip" the MSI's embedded cab into the folder of my choosing. To do the extraction, I'm using the WiX 3.6 DTF libraries, but am unable to determine how to change the folder structure.
So, for instance, if I ran the MSI installer, the target folder for "Component1" would be c:\Program Files(x86)\Company Name\Demo Product Installer\Component1\
, but at runtime in my extractor application, I'd like to put change that to c:\SomeOtherPlace\Demo Product Installer\Component1\
, preferably by changing the APPLICATIONFOLDER
directory path (see below).
For the MSI, I've defined the directory structure like this:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="APPLICATIONFOLDER" Name="Company Name">
<Directory Id="ProductFolder" Name="Demo Product Installer">
<Directory Id="Cmp1Folder" Name="Component1" />
<Directory Id="Cmp2Folder" Name="Component2" />
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
Then, in the code that needs to extract the files, I've done this:
var msiFilePath = "myInstallerFile.msi";
var targetFolder = @"c:\SomeOtherPlace\";
using (var msiPackage = new InstallPackage(msiFilePath, DatabaseOpenMode.ReadOnly))
{
msiPackage.WorkingDirectory = targetFolder;
var dirMapping = msiPackage.Directories;
if (dirMapping.ContainsKey("APPLICATIONFOLDER"))
{
//This doesn't work, but represents what I hope to do:
var oldInstallPath = dirMapping["APPLICATIONFOLDER"];
oldInstallPath.TargetPath = targetFolder;
}
msiPackage.UpdateDirectories();
msiPackage.ExtractFiles();
msiPackage.Close();
}
Is there a way to modify the folder structure like this at runtime using the DTF objects? I know I can just move the files around after the fact, but if I can do it this way, it'd be much cleaner.
Based on the hint ("You might be albe to do it with in memory updates of the tables...") from Chirtopher's answer, I was able to find a working solution:
Note that I also changed the DatabaseOpenMode to Transact.
Of course, if you wanted to do more advanced changes to the folder structure, you'd have to modify/insert/remove additional records from the Directory table. (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa368295(v=vs.85).aspx for reference)