更新:
查找组件的安装位置:有没有办法检测安装位置而不卸载注册表或C:\Windows\Installer?
Implementation :MSI如何存储这些东西是不应该被干预、试图修改或直接用于任何目的的实现细节--这一点非常清楚。您应该阅读MSI ,它是以Win32 functions的形式实现的,具有互补的COM wrappers,以便通过脚本语言进行访问。
MSI数据库主要存储在注册表中,但磁盘上也有组件--例如,%SystemDrive%\Windows\Installer (一个不应该以任何方式修改的超级隐藏文件夹)。MSI数据库存储在整个注册表的多个位置:
HKCR\InstallerHKCU\Software\Microsoft\InstallerHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\InstallerHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\UninstallHKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\UninstallHKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\InstallerEtc...有些是真实的,有些是别名,有些是合并。一切都有点模糊。再说一遍:implementation details --这是我们大家都熟知的委婉说法:“现在放弃吧,你?”:-)只需应用MSI获取所需的信息即可。
MSI API:上面要阅读的东西很多,可以通过MSI获取有关目录解析的信息。我们要做的是有点异国情调,我们必须为已安装的产品旋转一个会话对象,并运行两个标准操作(来自微软的内置MSI操作),以便解析所涉MSI (关于“成本”)的目录表和安装目录。以下是一个实际的样本:
请记录在案:
如何找到已安装的MSI安装程序的产品GUID?如何比较两个(或更多) MSI文件的内容? (在Orca和其他免费的MSI工具上)在不使用msiexec的情况下从命令行卸载MSI文件 (卸载MSI软件包的各种方法)代码语言:javascript复制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文件中的表上添加一个指向旧答案的链接。
解决了所有的:有点抓走了,然后再进行一次更新来解析所有已安装的软件包的所有目录。下面是一个脚本(测试不多):
代码语言:javascript复制' 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)链接
如何在VBScript中解析MSI路径?