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

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

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

msiexec /a foo.msi TARGETDIR=C:\EXTRACTHERE /qn 

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

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

szCommandLine [in]以空值终止的字符串,用于指定命令行属性设置。 这应该是格式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(); } } } } 

MSI文件是COM结构化存储 。 它基本上是一个数据库。 你可以在msdn上找到一些详细的文档:

  • 这是数据库API
  • 在这里,您可以找到有关复合二进制文件格式的一些信息
  • 这是关于Windows Installer的文档