我可以从C++或C#程序中提取MSI包的内容吗?

c00*_*0fd 6 c# c++ windows-installer extract

比方说,如果我有一个MSI安装文件,我可以从C#或C++程序中提取其内容而不安装它吗?

Chr*_*ter 9

通常,您可以执行管理安装以提取MSI的内容.

msiexec /a foo.msi TARGETDIR=C:\EXTRACTHERE /qn
Run Code Online (Sandbox Code Playgroud)

如果您不想退出流程,可以通过MsiInstallProduct函数直接与MSI互操作.

szPackagePath [in]以null结尾的字符串,用于指定Windows Installer程序包位置的路径.字符串值可以包含URL,网络路径,文件路径(例如file://packageLocation/package.msi)或本地路径(例如D:\ packageLocation\package.msi).

szCommandLine [in]以null结尾的字符串,用于指定命令行属性设置.这应该是格式Property = Setting Property = Setting的列表.有关更多信息,请参阅关于属性.

要执行管理安装,请在szCommandLine中包含ACTION = ADMIN.有关更多信息,请参阅ACTION属性.

请注意,虽然您可以自己声明P/Invoke,但Windows Instaler XML提供了一个非常好的.NET互操作库,称为Deployment Tools Foundation(DTF).Microsoft.Deployment.WindowsInstaller命名空间有一个名为Installer的类方法,它公开一个名为InstallProduct的静态方法.这是MsiInstallProduct的直接封装.

使用DTF库可以隐藏Win32 API上的丑陋,并在需要时正确实现IDisposable,以确保在需要时释放基础非托管句柄.

此外,DTF具有带InstallPackage类的Microsoft.DeploymentWindowwsInstaller.Package命名空间.此类公开了一个名为ExtractFiles()的方法,该方法将文件提取到工作目录.代码示例如下:

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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)