Ajay
Ajay

Reputation: 18411

How extract deployment files from MSI database

MSI database contains set of tables, and I can successfully enumerate File table, which has all deployable file' meta-deta. What I need to extract is the actual contents of those files. msiexec, lessmsi, 7-zip all can do it, but I couldn't find any source/API to do it.

What I've discovered it that all other (resource) files are in Binary table, and Data field can be used to get content of those files (like icons, custom DLL etc).

Further, I found and know that Media table contains information about the .CAB file (MSI has all content embedded with <MediaTemplate EmbedCab="yes"/>. This simply means the CAB file contains the actual content. I probably need to read contents from "Structured Storage" of the .msi file.

How to extract the contents of CAB/MSI file, using native C Msi* functions?

Upvotes: 0

Views: 3769

Answers (3)

Stein &#197;smul
Stein &#197;smul

Reputation: 42126

You have gotten many good answers already, including the use of dark.exe from the WiX toolkit. By downloading the WiX source code you should be able to get the code you need ready-made from there. I assume you may already have done this.

Chris has already linked to the DTF code you can check, but here is a link directly to dark.exe as well: https://github.com/wixtoolset/wix3/tree/develop/src/tools/dark. I would try both. This is C#, you seem to want native.

UPDATE: Before I get to the Win32 features you can use, check out this little summary of the C# DTF features: How to programmatically read the properties inside an MSI file?

Native Win32 functions: The database functions to deal with an MSI file can be found on MSDN (this is to deal with the MSI file as a database). There are also MSI Installer Functions (used to deal with the MSI file as an actual installer).

You can certainly find good examples of native code for this with a good Google search. Have fun!


BTW: It would help with a description of the actual problem you are trying to solve as well as what you need technically. There could - as always - be less involved ways to achieve what you need. Unless you are writing a security software or malware scanner or something super-involved.


And so it is clear: WiX's dark.exe fully decompiles MSI files into WiX source files and the resource files used to build them - you can then text and binary compare the various types of content (text compare for tables, binary compare for binaries, etc...). The process to do so via command line is described in the following answer: How can I compare the content of two (or more) MSI files? (this is about comparing MSI files, but one option to do so is to decompile them - see section on dark.exe - just for reference for others who find your question).


I like to link things together so we can find content easily at a later point in time. Strictly speaking it doesn't seem necessary here, you have what you need I think but others could perhaps benefit from some further links. Here are some related links:

Upvotes: 2

Christopher Painter
Christopher Painter

Reputation: 55571

Phil has given you the easy/simple answer but I thought I might give you a little more information since you've done some research. Checkout:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa372919(v=vs.85).aspx

This is where the structured storage is. You'll see something like Disk1.cab as the Name (PK) and binary data. The data is a CAB file with the file entry in the cab matching the File.File column. From there you can use the File.FileName column to get the short name and long name (you'll want the long name no doubt) and do a joint to the Component table to get the directory table ID.

You'll also need to recurse the directory table to build the tree of directories and know where to put the files.

Fun stuff. There's some libraries in C# that make this WAY simpler. Or just call msiexec /a as Phil says. :)

Upvotes: 3

PhilDW
PhilDW

Reputation: 20780

The most straightforward to extract all the files to some location is to install the product in "advertised" mode. If you do a:

msiexec /a [path to msi] TARGETDIR=[some folder]

you'll see what happens.

In C++ call MsiInstallProduct () with that command line.

Upvotes: 3

Related Questions