微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 PHP 读取 Windows InstallerMSI 文件属性

如何解决从 PHP 读取 Windows InstallerMSI 文件属性

我有一个 Windows MSI 文件,我需要以编程方式从中读取版本号。我唯一能看到这个版本的地方是文件详细信息的主题

MSI file

如果我能以某种方式阅读 Subject 的全部内容,那就没问题了,但有什么办法可以从 PHP 中获得它吗? PHP 正在 IIS Web 服务器中运行,如果这有帮助的话 ;-)

stat 对此没有帮助。

我考虑过对文件进行校验和,并且可以做到,但我确实需要真实版本。

解决方法

首先要注意两点:

  1. 我从未从 PHP 访问过 COM,但以下是一些使用 MSI API - COM automation 从 MSI 文件获取信息的 VBScript 示例。 There are also Win32 functions

  2. 您所指的那个字段不是版本字段,而是来自 MSI 的“摘要流”的文本字段——MSI 文件的一个特殊部分,带有各种“元信息”。 Summary Information Stream(全名)。

以下是获取真实版本的 MSI 文件的方法。这存储在 MSI 文件的属性 "ProductVersion" 中。至少有两种不同的方法可以检索它 - 通过将 MSI 文件作为会话打开或仅通过 SQL 查询访问属性表:

通过会话对象访问版本:

Const msiUILevelNone = 2
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
installer.UILevel = msiUILevelNone

Set s = installer.OpenPackage("C:\MySetup.msi",1)

MsgBox CStr(s.ProductProperty("ProductVersion"))

通过SQL再次访问MSI数据库(属性表):

Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")

' Open MSI database in read-only mode (0)
Set db = installer.OpenDatabase("C:\MySetup.msi",0)
Set view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'")
view.Execute

Set record = view.Fetch

MsgBox CStr(record.StringData(1))

然后是访问 SummaryStream 的问题——这正是你从它的外观中真正要问的——这是一个简单的烟雾测试,其中包含一些关于你可以检索哪些属性的提示——注意摘要流——损坏有多种可能(我不记得细节,但访问只读应该是安全的):

Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")

' Open MSI database in read-only mode (0)
Set db = installer.OpenDatabase("C:\MySetup.msi",0)
MsgBox CStr(db.SummaryInformation.Property(3))

' 1 = "Codepage"
' 2 = "Title"
' 3 = "Subject"
' 4 = "Author"
' 5 = "Keywords"
' 6 = "Comments"
' 7 = "Template"
' 8 = "LastAuthor"
' 9 = "Revision"
' 11 = "Printed"
' 12 = "Created"
' 13 = "Saved"
' 14 = "Pages"
' 15 = "Words"
' 16 = "Characters"
' 18 = "Application"
' 19 = "Security"
,

目前我无法为此找到本机 PHP 解决方案,因此我通过调用 Powershell 脚本暂时解决了这个问题,因为在那里做起来似乎更容易。

我现在有这个 PHP 代码: $version = exec("powershell.exe -file GetMsiVersion.ps1 MyFile.msi);

根据我上面的图片,$version 将包含 1.5.9,因此我什至不需要解释来自 Subject 的数据。

GetMsiVersion.ps1 Powershell 脚本具有以下代码:

function Get-Property ($Object,$PropertyName,[object[]]$ArgumentList) {
    return $Object.GetType().InvokeMember($PropertyName,'Public,Instance,GetProperty',$null,$Object,$ArgumentList)
}

function Invoke-Method ($Object,$MethodName,$ArgumentList) {
    return $Object.GetType().InvokeMember($MethodName,InvokeMethod',$ArgumentList)
}

$Path = $args[0]
$msiOpenDatabaseModeReadOnly = 0
$Installer = New-Object -ComObject WindowsInstaller.Installer
$Database = Invoke-Method $Installer OpenDatabase  @($Path,$msiOpenDatabaseModeReadOnly)
$View = Invoke-Method $Database OpenView  @("SELECT Value FROM Property WHERE Property='ProductVersion'")
Invoke-Method $View Execute
$Record = Invoke-Method $View Fetch
if ($Record) {
    Write-Output (Get-Property $Record StringData 1)
}

Invoke-Method $View Close @()

我会接受这是此时此地的最佳解决方案,但是,我希望这可以从 PHP 本地存档,因为我认为这是一个更好、更干净的解决方案 - 到那时我会接受它作为最佳答案(或者至少不接受我自己的临时解决方案)。

做一个exec有点邪恶;-)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。