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

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

本文关键字:MSI 提取 C++ 程序 我可以      更新时间:2023-10-16

比方说,如果我有MSI安装文件,我可以在不安装的情况下从C#或C++程序中提取其内容吗?

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

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

如果你不想脱离进程,你可以通过MsiInstallProduct函数直接与MSI进行互操作。

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

szCommandLine[in]一个以null结尾的字符串,用于指定命令行属性设置。这应该是一个格式为Property=SettingProperty=Setting的列表。有关详细信息,请参见关于特性。

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

请注意,虽然您可以自己声明p/Invoke,但有一个非常好的。NET互操作库,可与名为部署工具基础(DTF)的Windows Instaler XML一起使用。微软。部署。WindowsInstaller命名空间有一个名为Installer的类方法,它公开了一个称为InstallProduct的静态方法。这是MsiInstallProduct的直接封装。

使用DTF库可以避免Win32 API上的丑陋,并在需要时正确实现IDisposable,以确保在需要时释放底层非托管句柄。

此外,DTF拥有微软。DeploymentWindowwsInstaller。具有InstallPackage类的包命名空间。此类公开一个名为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安装程序的文档