更新:
查找组件的安装位置:有没有办法在没有卸载注册表或 C:\Windows\Installer 的情况下检测安装位置?
实施细节:MSI 如何存储这些东西是实施细节,不应干预、尝试修改或直接用于任何目的 - 只是为了清楚起见。您应该通过MSI API,它是作为Win32 函数实现的,带有互补的COM 包装器,以便通过脚本语言进行访问。
注册表: MSI 数据库主要存储在注册表中,但磁盘上也有组件 - 您引用其中的一些 - 例如%SystemDrive%\Windows\Installer(不应以任何方式修改的超级隐藏文件夹)。MSI 数据库存储在注册表中的多个位置:
HKCR\Installer
HKCU\Software\Microsoft\Installer
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Installer
Etc...
其中一些是真实的,一些是别名,一些是合并。这一切都有些模糊。再说一遍:implementation details-我们大家都知道的委婉说法:“现在就放弃吧,你愿意吗?” :-)。只需应用 MSI API 即可获取您需要的信息。
MSI API:上面有很多东西要阅读以达到重点,通过 MSI API 获取有关目录解析的信息。我们要做的有点奇怪,我们必须为已安装的产品启动一个会话对象并运行两个标准操作(Microsoft 的内置 MSI 操作)以解析 MSI 的目录表和安装目录问题(关于“成本核算”)。下面是一个实际示例:
作为记录:
Set installer = CreateObject("WindowsInstaller.Installer")
' Other test product codes: {2F73A7B2-E50E-39A6-9ABC-EF89E4C62E36}
productcode = Trim(InputBox("Please paste or type in the product code you want to look up details for:", _
"Find Product Details (test GUID provided):", "{766AD270-A684-43D6-AF9A-74165C9B5796}"))
If search = vbCancel Or Trim(productcode) = "" Then
WScript.Quit(0)
End If
Set session = installer.OpenProduct(productcode)
' Crucially, resolve the directory table and properties by running "MSI Costing"
session.DoAction("CostInitialize")
session.DoAction("CostFinalize")
' Can be any directory property from the Directory table in the MSI:
MsgBox session.Property("INSTALLFOLDER")
' Open the MSI in Orca to find the directory folder property names
抛出一个关于如何在 MSI 文件中列出表的旧答案的链接。
全部解决:有点得意忘形,并进行了一次更新以解析任何已安装软件包的所有目录。这是一个脚本(没有经过太多测试):
' https://stackoverflow.com/questions/17543132/how-can-i-resolve-msi-paths-in-vbscript
' On Error resume Next
Set installer = CreateObject("WindowsInstaller.Installer")
' Other test product codes: {2F73A7B2-E50E-39A6-9ABC-EF89E4C62E36}
const READONLY = 0
Dim DirList
productcode = Trim(InputBox("Please paste or type in the product code you want to look up details for:", _
"Find Product Details (test GUID provided):", "{766AD270-A684-43D6-AF9A-74165C9B5796}"))
If search = vbCancel Or Trim(productcode) = "" Then
WScript.Quit(0)
End If
Set session = installer.OpenProduct(productcode)
session.DoAction("CostInitialize")
session.DoAction("CostFinalize")
set view = session.Database.OpenView("SELECT * FROM Directory")
view.Execute
set record = view.Fetch
Do until record is Nothing
ResolvedDir = session.Property(record.StringData(1))
DirList = DirList + record.StringData(1) + " => " + ResolvedDir + vbCrLf
set record = view.Fetch
Loop
' Dismiss dialog with ESC key if it falls off screen
WScript.Echo DirList ' Use WScript.Echo due to MsgBox restrictions (number of characters)
链接: