这是question的后续跟进。
我正在使用这个稍微修改过的脚本来枚举所有已安装的MSI包:
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & _
strComputer & _
"\root\cimv2")
Set colSoftware = objWMIService.ExecQuery _
("SELECT * FROM Win32_Product")
If colSoftware.Count > 0 Then
For Each objSoftware in colSoftware
WScript.Echo objSoftware.Caption & vbtab & _
objSoftware.Version
Next
Else
WScript.Echo "Cannot retrieve software from this computer."
End If
然而令人惊讶的是它的糟糕表现。在我的XP盒子上枚举34个已安装的MSI软件包需要3到5分钟!
相比之下,除此之外的Linux盒子需要花费7秒才能枚举1400+ RPM ... 叹息
有关此的任何线索吗?
答案 0 :(得分:6)
极端缓慢是枚举Win32_Products
的已知/常见问题如果您需要备用解决方案,请考虑使用“卸载”注册表项构建您自己的产品列表(如您所提到的original question的一个答案中所述)。
枚举Uninstall的一般参考:
要远程执行 ,请使用WMI注册表类StdRegProv。 TechNet甚至可以方便地提供一个使用StdRegProv来完成您想要的事情的简单示例: How do I list all the installed applications on a given machine
答案 1 :(得分:4)
Win32_Product WMI类是如此之慢,因为它正在进行一致性检查 - 每次使用时都使用Msiexec.exe处理每个包。
在此页面上使用更好的方法查看问题和vbscript代码:http://csi-windows.com/toolkit/288-win32product-wmi-class-replacement
答案 2 :(得分:2)
当您使用在msi.h中声明的api函数时,您的速度很快。 我正在使用api作为我的软件software-uptodate,并且枚举数百个数据包需要一秒钟。
答案 3 :(得分:1)
我怀疑网络问题,Wireshark证明我是对的。
Windows Installer似乎很乐意尝试重新打开所有原始.msi文件,包括那些生活在网络共享上的文件。
答案 4 :(得分:1)
这对我有用,并且避免了WMI方法的缓慢:
Dim installer
Set installer = CreateObject("WindowsInstaller.Installer")
Dim productCode, productName
For Each productCode In installer.Products
productName = installer.ProductInfo(productCode, "ProductName")
WScript.Echo productCode & " , " & productName
Next
从http://msdn.microsoft.com/en-us/library/windows/desktop/aa369432(v=vs.85).aspx
了解有关Installer
对象的更多信息