Can I extract contents of MSI package from within C++ or C# program?

这一生的挚爱 提交于 2019-11-29 20:40:09

问题


Say, if I have an MSI installation file, can I extract its contents from a C# or C++ program without installing it?


回答1:


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();
            }
        }
    }
}



回答2:


An MSI file is a COM structured storage. It is basically a database. You can find some detailed documentation on msdn:

  • Here is the database API
  • Here you can find some info about a compound binary file format
  • Here is the doc about Windows Installer


来源:https://stackoverflow.com/questions/12489317/can-i-extract-contents-of-msi-package-from-within-c-or-c-sharp-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!