Reputation: 129
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
Upvotes: 1
Views: 1586
Reputation:
I'm sure that it can be done but you'll have to wait for objWMIService to timeout every time it's ping a device that is down. Conversely you can take a call me when your ready approach. Create a script that check for the image on the local machine and saves it's findings to a file on the sever. You can then have Group Policy schedule a task on all the machines to run new script locally.
Updated: I tightened up your code a bit to reducing the overall complexity.
On Error Resume Next
And
On Error GoTo 0
Needed to be move inside the for each loop. Since On Error GoTo 0 was outside the loop the Err object couldn't be reset to 0 until the for each loop exited.
Function GetWmiObjects(wmi, wql)
Dim items, item, i, result
Set items = wmi.ExecQuery(wql)
For Each item In items
On Error Resume Next
If Err.Number = 0 Then
i = UBound(result) + 1
ReDim Preserve result(i)
Set result(i) = item
End If
On Error GoTo 0
Next
GetWmiObjects = result
End Function
Upvotes: 0
Reputation: 338316
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
Upvotes: 1