Search code examples
vbscriptwmi

VBScript WMI Class and Property Exist


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

Solution

  • 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