从 PHP 读取 Windows 安装程序(MSI 文件)属性
Read Windows Installer (MSI file) attributes from PHP
我有一个 Windows MSI 文件,我需要以编程方式从中读取版本号。我唯一能看到这个版本的地方是在文件详细信息的 Subject 中:
如果我能以某种方式阅读 Subject 的全部内容,那就没问题了,但是有什么方法可以从 PHP 中获取吗? PHP 在 IIS Web 服务器中是 运行,如果这有帮助的话;-)
stat
对此没有帮助。
我考虑过对文件进行校验和,并且可以做到,但我确实需要真实版本。
首先要做两件事:
我从未从 PHP 访问过 COM,但下面是一些使用 MSI API - COM automation. There are also Win32 functions.
从 MSI 文件获取信息的 VBScript 示例
您引用的那个字段不是版本字段,而是来自 MSI 的“摘要流”的文本字段 - MSI 文件的一个特殊部分,包含各种“元信息”。 Summary Information Stream(全名)。
这是获取 MSI 文件的真实版本的方法。这存储在 MSI 文件中的 属性 "ProductVersion"
中。至少有两种不同的方法来检索它 - 通过将 MSI 文件作为会话打开或仅通过 SQL 查询访问 属性 table:
通过Session对象访问版本:
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 数据库 (属性 table):
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 的问题——从它的外观来看,这是你真正要问的——这是一个简单的冒烟测试,其中包含一些关于你可以检索哪些属性的提示——注意摘要stream - 损坏可能有多种方式(我不记得细节,但以只读方式访问应该是安全的):
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.[=16= 的数据]
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, 'Public, Instance, InvokeMethod', $null, $Object, $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
有点邪恶 ;-)
我有一个 Windows MSI 文件,我需要以编程方式从中读取版本号。我唯一能看到这个版本的地方是在文件详细信息的 Subject 中:
如果我能以某种方式阅读 Subject 的全部内容,那就没问题了,但是有什么方法可以从 PHP 中获取吗? PHP 在 IIS Web 服务器中是 运行,如果这有帮助的话;-)
stat
对此没有帮助。
我考虑过对文件进行校验和,并且可以做到,但我确实需要真实版本。
首先要做两件事:
我从未从 PHP 访问过 COM,但下面是一些使用 MSI API - COM automation. There are also Win32 functions.
从 MSI 文件获取信息的 VBScript 示例您引用的那个字段不是版本字段,而是来自 MSI 的“摘要流”的文本字段 - MSI 文件的一个特殊部分,包含各种“元信息”。 Summary Information Stream(全名)。
这是获取 MSI 文件的真实版本的方法。这存储在 MSI 文件中的 属性 "ProductVersion"
中。至少有两种不同的方法来检索它 - 通过将 MSI 文件作为会话打开或仅通过 SQL 查询访问 属性 table:
通过Session对象访问版本:
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 数据库 (属性 table):
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 的问题——从它的外观来看,这是你真正要问的——这是一个简单的冒烟测试,其中包含一些关于你可以检索哪些属性的提示——注意摘要stream - 损坏可能有多种方式(我不记得细节,但以只读方式访问应该是安全的):
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.[=16= 的数据]
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, 'Public, Instance, InvokeMethod', $null, $Object, $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
有点邪恶 ;-)