My company is trying to find what machines were not loaded with our images. We added in WMI a class called Revision_Detail, but due to inconsistencies, it was not populated on all versions of our images.
I put together the below to check if the Revision_Detail exists, then check if it is not null. If it is null it reverts to ImageRevision class, which everyone of our images has.
My problem is the function I came across (and are using), cycles through all of CIMV2 classes and is a bit slow.
Is there a way to just execute the query and catch the error that Revision Detail doesn't exists?
Function WMIClassExists(strComputer, WMIClassName)
WMIClassExists = vbFalse
Dim objWMIService: Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Dim colClasses: Set colClasses = objWMIService.SubclassesOf()
Dim objClass
For Each objClass In colClasses
if instr(objClass.Path_.Path,WMIClassName) Then
WMIClassExists = vbTrue
End if
Next
Set objWMIService = Nothing
Set colClasses = Nothing
End Function
Set wshNetwork = WScript.CreateObject("WScript.Network")
strComputer = wshNetwork.ComputerName
If WMIClassExists(strComputer,"Revision_Detail") Then
'Found Revision_Detail
WSCript.Echo strWMIClass & " WMI class does exists on " & strComputer
Set Wmi = GetObject("winmgmts:\\" & strComputer & "\ROOT\CIMV2")
SET colItems = Wmi.ExecQuery("SELECT * FROM Revision_Detail")
For Each objItem in colItems
if IsNull(objItem.CurrentBuild) Then
'If CurrentBuild doesnt exist, check ImageRevision
SET colItems2 = Wmi.ExecQuery("SELECT * FROM ImageRevision")
For Each objItem2 in colItems2
wscript.echo "ImageRevision: " & objItem2.ImageRevision
Next
else
'Revision_Detail exists and is not blank
wscript.echo "CurrentBuild: " & objItem.CurrentBuild
wscript.echo "StartBuild: " & objItem.StartBuild
end if
Next
Else
'Must not be an our image
WSCript.Echo strWMIClass & " WMI class does not exists on " & strComputer
End if
Is there a way to just execute the query and catch the error that Revision Detail doesn't exists?
Sure that's possible. Catching errors in VBScript is done with On Error Resume Next
(docs).
Since the WMI object collections are a bit awkward to work with, I have created a helper function that executes a WMI query and returns an array instead of a collection:
Function GetWmiObjects(wmi, wql)
Dim items, item, i, result
Set items = wmi.ExecQuery(wql)
' count items
On Error Resume Next
i = 0
For Each item In items
If Err.Number = 0 Then i = i + 1
Next
On Error GoTo 0
' allocate array of the proper size
ReDim result(i - 1)
' transfer items to array
If i > 0 Then
i = 0
For Each item In items
Set result(i) = item
i = i + 1
Next
End If
GetWmiObjects = result
End Function
Now it's easy to do:
Set wmi = GetObject("winmgmts:\\.\ROOT\CIMV2")
Revision_Detail = GetWmiObjects(wmi, "SELECT * FROM Revision_Detail")
If Count(Revision_Detail) = 0 Then
Wscript.Echo "Revision_Detail not found"
Else
Wscript.Echo Revision_Detail(0).CurrentBuild
End If
where Count
is a convenience function that returns the size of an array:
Function Count(array)
Count = UBound(array) + 1
End Function