比如说,如果我有一个 MSI 安装文件,我可以从 C# 或 C++ 程序中提取其内容而不安装它吗?
2 回答
通常,您可以执行管理安装以提取 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();
}
}
}
}