Say, if I have an MSI installation file, can I extract its contents from a C# or C++ program without installing it?
2 Answers
Typically you can perforrm an Administrative installation to extract the contents of an MSI.
msiexec /a foo.msi TARGETDIR=C:\EXTRACTHERE /qn
If you don't want to go out of process you can interop directly with MSI via the MsiInstallProduct function.
szPackagePath [in] A null-terminated string that specifies the path to the location of the Windows Installer package. The string value can contain a URL a network path, a file path (e.g. file://packageLocation/package.msi), or a local path (e.g. D:\packageLocation\package.msi).
szCommandLine [in] A null-terminated string that specifies the command line property settings. This should be a list of the format Property=Setting Property=Setting. For more information, see About Properties.
To perform an administrative installation, include ACTION=ADMIN in szCommandLine. For more information, see the ACTION property.
Note that while you can declare the P/Invoke yourself, there is a really good .NET interop library available with Windows Instaler XML called Deployment Tools Foundation (DTF). The Microsoft.Deployment.WindowsInstaller namespace has a class method called Installer that exposes a static method called InstallProduct. This is a direct encapsulation of MsiInstallProduct.
Using the DTF libraries hides you from the ugliness on the Win32 API and correctly implements IDisposable where needed to ensure that underlying unmanaged handles are released where needed.
Additionally DTF has the Microsoft.DeploymentWindowwsInstaller.Package namespace with the InstallPackage class. This class exposes a method called ExtractFiles() that extracts the files to the working directory. An example of code looks like:
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Package;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using( var package = new InstallPackage(@"C:\test.msi", DatabaseOpenMode.ReadOnly))
{
package.ExtractFiles();
}
}
}
}

- 54,556
- 6
- 63
- 100
-
Thanks and sorry for this delay. Just curious if this is available from an ASP.NET web app? – c00000fd Sep 21 '12 at 01:59
-
1Sorry, if I'm asking something very simple. When I include your two 'use' lines I get this: "error CS0234: The type or namespace name 'Deployment' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)" – c00000fd Sep 23 '12 at 02:53
-
You have to install WiX and add a reference to that library in the WiX SDK directory. – Christopher Painter Sep 23 '12 at 03:20
-
Ooh. I can't install anything on the server side. It must be stock IIS libraries. – c00000fd Sep 23 '12 at 03:50
-
You need Microsoft.Deployment.WindowsInstaller.dll and Microsoft.Deployment.WindowsInstaller.Package.dll for the code to work. (part of wix). I don't think you have to install these. Take them from WIX and include them in your project. You could even make them embedded and serve them to your app with AppDomain.CurrentDomain.AssemblyResolve. – Wolf5 Apr 08 '13 at 07:57
An MSI file is a COM structured storage. It is basically a database. You can find some detailed documentation on msdn:

- 29,228
- 8
- 68
- 105
-
1Thanks. Although it's all pretty overwhelming at this point for me... Any links to a C# code that can do the extraction? – c00000fd Sep 19 '12 at 06:35
-
3He just wants to know how to extract the contents. There are API's for that. He doesn't need to understand the database structure at a binary level. – Christopher Painter Sep 19 '12 at 13:02