如何以编程方式读取MSI文件中的属性?

时间:2008-11-18 14:14:55

标签: wix windows-installer installer msiexec dtf

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

例如,给定一个msi文件名Testpackage.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是一个很好的选择,如果这可以以编程方式实现,那么我可以使用它来生成自动发行说明。并且也在卸载程序中。

5 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:6)

您可以使用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

答案 2 :(得分:6)

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

包装器名为“部署工具基础”(DTF),这里是基本描述:“部署工具基础是一组丰富的.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 - 完整的Windows Installer API基于.NET的类库。
  • 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.chm DTFAPI.chm 。绝对优秀的对象模型及其用法文档。
  • 有关更多DTF详细信息,请参阅this serverfault.com post
  • 使用WiX的一些入门建议:MSI vs nuget packages: which are is better for continuous delivery?

答案 3 :(得分:3)

这是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 

答案 4 :(得分:1)

我在lessmsi找到了一个轻量级的非程序化解决方案。它显然使用wix,只是将整个.msi爆炸到指定的文件夹中。 (它也有一个用户界面,但在Win7上对我来说效果不佳。)