VBScript WMI类和属性存在

时间:2016-06-09 17:37:57

标签: vbscript wmi

我的公司正试图找到哪些机器没有加载我们的图像。我们在WMI中添加了一个名为Revision_Detail的类,但由于不一致,我们的图像的所有版本都没有填充它。

我把下面的内容放在一起检查是否存在Revision_Detail,然后检查它是否为null。如果它为null,它将恢复为ImageRevision类,我们的每个图像都有。

我的问题是我遇到的功能(并且正在使用),循环遍历所有CIMV2类并且有点慢。

有没有办法只执行查询并捕获修订详细信息不存在的错误?

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

2 个答案:

答案 0 :(得分:1)

  

有没有办法只执行查询并捕获修订版详细信息不存在的错误?

确定可能。 VBScript中的捕获错误是使用On Error Resume Nextdocs)完成的。

由于WMI对象集合使用起来有点尴尬,我创建了一个辅助函数来执行WMI查询并返回一个数组而不是一个集合:

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

现在很容易做到:

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

其中Count是一个返回数组大小的便捷函数:

Function Count(array)
    Count = UBound(array) + 1
End Function

答案 1 :(得分:0)

我确信它可以完成,但是你必须等待objWMIService在每次ping一个已关闭的设备时超时。 相反,当你准备好接近时,你可以打电话给我。 创建一个脚本,检查本地计算机上的映像,并将其结果保存到服务器上的文件中。然后,您可以让组策略在所有计算机上安排任务以在本地运行新脚本。

<强>更新 我收紧了你的代码以降低整体复杂性。

  

On Error Resume Next

并且

  

On Error GoTo 0

需要在每个循环中移动。由于On Error GoTo 0在循环之外,Err对象无法重置为0,直到退出每个循环。

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