8

我用 WiX 创建了一个 MSI 文件。源 WiX 文件包含如下版本信息:

<Product Id="..." 
         Name="..." 
         Language="1033" 
         Version="1.0.0.1" 
         Manufacturer="..." 
         UpgradeCode="...">

MSI 文件似乎工作正常:它会安装、卸载、当我增加版本号时会升级等。

但是,当我尝试通过调用 MsiGetFileVersion() API 获取有关此文件的版本信息时,它返回错误 1006(ERROR_FILE_INVALID 文件不包含版本信息。)

因此我的问题是:如何(以编程方式,在 C++ 中)检索 MSI 文件的版本号?或者,换一种说法,版本信息应该放在 WiX 文件的哪个位置才能通过 MsiGetFileVersion() 检索?

更多信息:Windows XP 上的 MSI 3.0 和 Vista 上的 MSI 4.0 也会出现同样的错误。

4

3 回答 3

7

作为参考,这是我在构建过程中使用的一个 VBscript 示例,用于在创建 boostrapper 之前获取此类示例。

Dim installer, database, view, result

Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase ("my.msi", 0)

Dim sumInfo  : Set sumInfo = installer.SummaryInformation("my.msi", 0)
sPackageCode =  sumInfo.Property(9) ' PID_REVNUMBER = 9, contains the package code.

WScript.Echo getproperty("ProductVersion")
WScript.Echo getproperty("ProductVersion")
WScript.Echo sPackageCode
WScript.Echo 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 
于 2009-05-03T02:03:08.473 回答
6

出于完整性考虑, ::MsiGetFileVersion() 是一个从 PE 文件(.exe 或 .dll)读取版本资源信息的函数,与 Windows Installer 的方式相同。这对于使用构建工具(例如WiX 工具集)很重要,因此它们可以正确填充 File/@Version 信息。它不会让您从 MSI 中获取版本信息。正如@sascha 所示,您可以查询“ProductVersion”的属性表,或者您可以使用 ::MsiGetProductProperty() 来执行相同的操作。

于 2009-05-03T17:19:40.597 回答
4

找到了解决方案:而不是调用 MsiGetFileVersion(),调用:

MSIHANDLE hProduct = NULL;
MsiOpenPackage( pszPath, &hProduct );

MsiGetProductProperty( hProduct, _T("ProductVersion"), pszVersion, &dwSizeVersion );

MsiCloseHandle( hProduct );

(省略错误处理)

于 2009-05-03T00:29:18.433 回答