【问题标题】:How can I programmatically read the properties inside an MSI file?如何以编程方式读取 MSI 文件中的属性?
【发布时间】:2008-11-18 14:14:55
【问题描述】:

有没有办法读取MSI 文件中的属性?

例如,给定一个名为 Testpackage.msi 的 MSI 文件,我需要找到

productName
PackageCode
version

我将在 WMI 卸载中使用它

string objPath = string.Format("Win32_Product.IdentifyingNumber='{0}', Name='{1}', Version='{2}'", "{AC9C1263-2BA8-4863-BE18-01232375CE42}", "testproduct", "10.0.0.0");

如果可以通过编程方式实现,使用Orca 是一个不错的选择。然后我可以使用它来生成自动发行说明。在卸载程序中也是如此。

【问题讨论】:

    标签: wix installation windows-installer dtf


    【解决方案1】:

    您可以使用COM-based API for working with MSI,并执行类似的操作

    Function GetVersion(ByVal msiName)
    
        Const msiOpenDatabaseModeReadOnly = 0
        Dim msi, db, view
    
        Set msi = CreateObject("WindowsInstaller.Installer")
        Set db = msi.OpenDataBase(msiName, msiOpenDatabaseModeReadOnly)
        Set view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'")
        Call view.Execute()
    
        GetVersion = view.Fetch().StringData(1)
    
    End Function
    

    【讨论】:

    • 还可以查看 MsiInfo.exe 命令行工具(也是 Windows SDK 的一部分)。它可以读写一个MSI的摘要信息(包括Oh-so-painful Package Code)
    • 请参阅下面的答案,了解我认为访问 MSI 的更简单、更可靠的方法。
    【解决方案2】:

    WiX 工具集WiX quick-start tips(资源链接的集合)。 WiX 安装 DTF。


    我只想提一下,现在事情变得更加容易了。 Windows Installer 对象模型有一个完整的 .NET 包装器,因此您可以避免任何 COM 互操作的笨拙

    DTF - 入门:主文件:Microsoft.Deployment.WindowsInstaller.dll

    1. Download and install the WiX toolkit
    2. WixInstallPath\SDK 目录中找到以下文件

    包装器称为“Deployment Tools Foundation”(DTF),基本描述如下:“Deployment Tools Foundation 是一组丰富的 .NET 类库和相关资源,它们组合在一起将 Windows 部署平台技术带入 .NET 世界。它旨在大大​​简化与部署相关的开发任务,同时仍然公开底层技术的完整功能

    这是一个精简的动手示例

    using (var db = new Database(FullPath, DatabaseOpenMode.ReadOnly))
    {    
      PackageCode = db.SummaryInfo.RevisionNumber;
      AppVendor = db.SummaryInfo.Author;
      AppName = db.SummaryInfo.Title;
      ProductName = db.SummaryInfo.Subject;
      ProductCode = (string)db.ExecuteScalar("SELECT `Value` FROM "+
                     "`Property` WHERE `Property` = 'ProductCode'");
      AppVersion = (string)db.ExecuteScalar("SELECT `Value` FROM "+
                     "`Property` WHERE `Property` = 'ProductVersion'");
      UpgradeCode = (string)db.ExecuteScalar("SELECT `Value` FROM "+
                     " `Property` WHERE `Property` = 'UpgradeCode'");
    }
    

    主要 DTF 文件(后两个是最常用的):

    • Microsoft.Deployment.Compression.dll - 归档打包和解包框架。
    • Microsoft.Deployment.Compression.Cab.dll - 实现压缩包归档打包和解包。
    • Microsoft.Deployment.Resources.dll - 用于在可执行文件中读取和写入资源数据的类。
    • Microsoft.Deployment.WindowsInstaller.dll - 完整的基于 .NET 的 Windows Installer API 类库。
    • Microsoft.Deployment.WindowsInstaller.Package.dll - 用于处理 Windows Installer 安装和补丁包的扩展类。

    只需创建一个 C# 项目,引用这些文件,然后使用您想要和需要的任何控件编写您自己的部署应用程序。目前我还没有准备好 DTF 工具,但请参阅 this sample 了解 C# 程序如何工作的一般概念。

    • DTF 包含在 WIX 中。 Download WiX from here
    • DTF dll 位于主 WiX 安装文件夹的 SDK 文件夹中(默认位置为:%ProgramFiles(x86)%\WiX Toolset v3.10\SDK)。当您看到此内容时,版本号可能会有所不同。只需在 %ProgramFiles(x86)% 下查找 WiX 文件夹即可。
    • 在“doc”文件夹中查找 DTF 帮助文件DTF.chmDTFAPI.chm。对象模型及其用法的绝对优秀文档。
    • 有关更多 DTF 详细信息,请参阅 this serverfault.com post
    • Some starter suggestions for working with WiX

    【讨论】:

    • DTF 隐藏在 WixInstallPath\SDK 目录,Microsoft.Deployment.*.dlls 中。
    【解决方案3】:

    您可以使用Microsoft's Orca.exe。 Orca 将允许您打开 MSI 并编辑/查看其中的所有表格。您必须下载整个 Windows SDK 才能获得它,但谢天谢地,它是免费的。

    另一种选择(由于 SDK 的下载大小可能会更快)是使用来自 WiX project 的 dark.exe。 Dark 是一个 MSI 反编译器,它将所有内容导出到 XML 文件和资源集合中。它输出的 XML 将包含您要查找的信息。

    【讨论】:

    【解决方案4】:

    这是 VBScript 中的一个类似示例,我在创建引导程序可执行文件时将其用作构建过程的一部分...

    Option Explicit
    Const MY_MSI = "product.msi"
    
    Dim installer, database, view, result, sumInfo, sPackageCode
    
    Set installer = CreateObject("WindowsInstaller.Installer")
    Set database = installer.OpenDatabase (MY_MSI, 0)
    
    Set sumInfo = installer.SummaryInformation(MY_MSI, 0)
    sPackageCode =  sumInfo.Property(9) ' PID_REVNUMBER = 9, contains the package code.
    
    WScript.Echo "ProductVersion=" & getproperty("ProductVersion")
    WScript.Echo "ProductCode=" & getproperty("ProductCode") 
    WScript.Echo "PackageCode=" & sPackageCode 
    WScript.Echo "ProductName=" & getproperty("ProductName") 
    
    Function getproperty(property)
    
        Set view = database.OpenView ("SELECT Value FROM Property WHERE Property='" & property & "'")
        view.Execute
        Set result = view.Fetch
        getproperty = result.StringData(1)
    
    End Function 
    

    【讨论】:

      【解决方案5】:

      我在lessmsi 中找到了一个轻量级的非编程解决方案。它显然使用 wix 并将整个 .msi 分解到指定的文件夹中。 (它也有一个 UI,但它在 Win7 上对我来说不是很好)。

      【讨论】:

      • 什么渲染得不好?请在谷歌代码网站上告诉我,我会调查的。或者,由于它是完全开源的,请随意提交补丁;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 2014-03-24
      • 1970-01-01
      相关资源
      最近更新 更多