9

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

4

2 回答 2

12

通常,您可以执行管理安装以提取 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=Setting Property=Setting 格式的列表。有关详细信息,请参阅关于属性。

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

请注意,虽然您可以自己声明 P/Invoke,但有一个非常好的 .NET 互操作库可用于Windows Instaler XML ,称为部署工具基础 (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();
            }
        }
    }
}
于 2012-09-19T12:32:36.860 回答
4

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

  • 是数据库API
  • 在这里您可以找到有关复合二进制文件格式的一些信息
  • 是有关 Windows Installer 的文档
于 2012-09-19T06:22:28.737 回答