dm4ever,
Thank you for the information!
But I have a lot of Windows 2003 Servers that are configured that way in my environment.
Is there any other alternative to eneumerate the software installed on the Windows 2003 Server machines?
I found an MSI script that can also enumerate the installed software from
However, it can only be run on the console of the machine to enumerate the installed software.
I modified the script to enumerate the product name and version in a command prompt mode, but I don't think that this script can be modidied to run remotely like WMI script. However, the script does run much faster than WMI script. Do you have any idea how to modify this script so that I can run remotely?
I hate to use a method to copy the script to the remote machine, run it, and collect the data back since some of our servers have their admin share disabled.
The code I have so far is listed below:
Dim WI, ProgramObject, AEnum(), sID, oProds, i2
Set WI = CreateObject("WindowsInstaller.Installer") '--create Installer object.
Set oProds = WI.Products '-- Windows Installer Products collection.
i2 = oProds.count
'-- Fill array with IDs of installed software.
If (i2 > 0) then '-- if there are W.I. installations then ....
ReDim AEnum(i2 - 1)
For i = 0 to (i2 - 1)
AEnum(i) = oProds.Item(i) '-- .... collect an array of the Product IDs.
Next
'-- describe first installed program returned in list of IDs:
'sID = AEnum(0) '-- first product ID.
For Each sID In AEnum
Set ProgramObject = GetProduct(sID) '-- Get Product object, an instance of MSIProduct class for this Product ID.
If Not ProgramObject Is Nothing Then '-- test for success in returning a Product object.
Wscript.Echo ProgramObject.Name & vbTab & ProgramObject.Version
End If
Set ProgramObject = Nothing
Next
End If
Set oProds = Nothing
Set WI = Nothing
Function GetProduct(sGUID)
Dim RetGP, ObMSIGP
On Error Resume Next
Set ObMSIGP = New MSIProduct
RetGP = ObMSIGP.GetP(sGUID)
If (RetGP = True) Then
Set GetProduct = ObMSIGP
End If
Set ObMSIGP = Nothing
End Function
Class MSIProduct
Private WI, sID, DB, BooDB, View, Rec
Private AData(), AFeats()
Public Function GetP(ProdGUID)
Dim AProps, i, i2, sItem, SL
On Error Resume Next
Err.clear
i = WI.ProductState(ProdGUID)
If (Err.number <> 0) or (i < 2) Then '-- Not installed.
GetP = False
Exit Function
End If
AProps = array("ProductName", "VersionString", "InstallDate", "Publisher", "LocalPackage", "InstallLocation")
sID = ProdGUID
'-- first Get most basic properties of product.
'-- InstallLocation is Not included here because it's often missing.
'-- InstallSource is Not included because it's Not of much use, only telling the path
'-- of MSI file at time of install.
For i = 0 to 5
sItem = AProps(i)
AData(i) = WI.ProductInfo(sID, sItem)
Next
'-- Collect list of features into the AFeats array.
ReDim AFeats(0) '-- Set at least one array item For return If no features.
AFeats(0) = ""
Set SL = WI.Features(sID)
If (isEmpty(SL) = False) Then
i = SL.Count
If (i > 0) Then
ReDim AFeats(i - 1)
For i2 = 0 to (i - 1)
AFeats(i2) = SL.Item(i2)
Next
End If
Set SL = Nothing
End If
GetDB AData(4) '-- Get database object If LocalPackage path is valid.
GetP = True
End Function
Public Property Get Name()
Name = AData(0)
End Property
'-- Publisher -------------------
Public Property Get Company()
Company = AData(3)
End Property
'-- Version -------------------
Public Property Get Version()
Version = AData(1)
End Property
'-- InstallDate -------------------
Public Property Get InstallDate()
InstallDate = AData(2)
End Property
'-- MSIFilePath -------------------
Public Property Get MSIFilePath()
MSIFilePath = AData(4)
End Property
'-- parent folder path of installed program.
Public Property Get ProgramPath()
ProgramPath = AData(5)
End Property
'-- Features as array. If none avail. Then Features(0) = ""
Public Property Get Features()
Features = AFeats
End Property
'-- Boolean value - whether or not feature is currently installed.
Public Property Get FeatureInstalled(sFeat)
Dim i3
On Error Resume Next
i3 = WI.FeatureState(sID, sFeat)
If (i3 = 3) Then
FeatureInstalled = True
Else
FeatureInstalled = False
End If
End Property
'-- feature parent. Returns parent feature name or "none". --------------
Public Property Get FeatureParent(sFeat)
Dim s1
On Error Resume Next
s1 = WI.FeatureParent(sID, sFeat)
If (len(s1) = 0) Then s1 = "none"
FeatureParent = s1
End Property
'-- feature description. This is available from the Session object but that would mean
'-- creating an installation session just to get this info. Since the database had to be
'-- opened anyway, the description can be retrieved from the Feature table. -------
'-- This returns feature description, if any. In many cases description is missing.
'-- In that Case it returns "none".
Public Property Get FeatureDescription(sFeat)
Dim s1
If (BooDB = False) Then
FeatureDescription = ""
Exit Property
End If
On Error Resume Next
Set View = DB.OpenView("SELECT `Description` FROM `Feature` WHERE `Feature` = '" & sFeat & "'")
View.execute
Set Rec = View.Fetch
If Not Rec is Nothing Then
s1 = Rec.stringdata(1) '--description.
If (len(s1) = 0) Then s1 = "none"
FeatureDescription = s1
Set Rec = Nothing
End If
Set View = Nothing
End Property
'-- Property that enables checking whether MSI file was available and whether database was successfully opened.
Public Property Get HaveDatabase() '--boolean.
HaveDatabase = BooDB
End Property
'-- feature components. returns array of component names for given feature. If failed, returns array(0) = "" ---------
Public Property Get Components(sFeature)
Dim s1, AComps(), iComps
ReDim AComps(0)
AComps(0) = ""
If (BooDB = False) Then
Components = AComps
Exit Property
End If
On Error Resume Next
iComps = 0
Set View = DB.OpenView("SELECT `Component_` FROM `FeatureComponents` WHERE `Feature_` = '" & sFeature & "'")
View.execute
Do
Set Rec = View.Fetch
If Rec is Nothing Then Exit Do
s1 = Rec.stringdata(1)
If (len(s1) > 0) Then
ReDim preserve AComps(iComps)
AComps(iComps) = s1
iComps = (iComps + 1)
End If
s1 = ""
Loop
Set Rec = Nothing
Set View = Nothing
Components = AComps
End Property
'-- Get array of files included in given component as: FileName|version. return array(0) = "" If failed.
Public Property Get Files(sComponent)
Dim s1, AFils(), iFils
ReDim AFils(0)
AFils(0) = ""
If (BooDB = False) Then
Files = AFils
Exit Property
End If
On Error Resume Next
iFils = 0
Set View = DB.OpenView("SELECT `FileName`, `Version` FROM `File` WHERE `Component_` = '" & sComponent & "'")
View.execute
Do
Set Rec = View.Fetch
If Rec is Nothing Then Exit Do
s1 = Rec.stringdata(1)
If (len(s1) > 0) Then
ReDim preserve AFils(iFils)
s1 = s1 & "|" & Rec.stringdata(2)
AFils(iFils) = s1
iFils = (iFils + 1)
End If
s1 = ""
Loop
Set Rec = Nothing
Set View = Nothing
Files = AFils
End Property
'--/////////// Private ///////////////------------------
Private Sub Class_Initialize()
BooDB = False
Set WI = CreateObject("WindowsInstaller.Installer")
ReDim AData(5)
End Sub
Private Sub Class_Terminate()
Set DB = Nothing
Set WI = Nothing
End Sub
'-- Get Database object for package file so that feature and component info. can be extracted.
'-- The OpenDatabase Function of the Installer object will return a database object that provides
'-- access to the numerous tables that collectively hold the information about what the program
'-- is, what features are included, what components make up those features, what files and
'-- Registry settings make up those components, etc.
'-- To get the Database object a file path to the MSI install file is needed.
'-- That was retrieved through the "LocalPackage" value of the Installer.ProductInfo Property.
'-- If no local MSI file is found then the database cannot be opened and some info. will
'-- not be available.
Private Sub GetDB(sPath)
Dim FSO
Err.clear
On Error Resume Next
Set FSO = CreateObject("Scripting.FileSystemObject")
If (FSO.FileExists(sPath) = False) Then
Set FSO = Nothing
Exit Sub
End If
Set DB = WI.OpenDatabase(sPath, 0) '-- database object.
If (Err.number = 0) Then BooDB = True '-- success. BooDB = True informs other functions that
'-- a database object has been retrieved and can be used.
Set FSO = Nothing
End Sub
End Class
Thanks again!
CluM09