在我的程序中,我正在使用WMI界面查询有关程序正在运行的硬件的大量信息。然后,我将这些信息放入列表中,以帮助以后显示它,但除此之外,目前还没有其他事情要做。到目前为止,此方法已经很好地解决了问题,但是存在一个主要问题:有时查询是/返回(尚不知道哪一个!)Nothing并生成NullReferenceException

现在,显然我可以将其包装在“尝试/捕获”中,然后以自己的方式进行。但是,我想避免这样做,因为我将查询数百位信息,而其中数百位信息可能会导致异常。这只是草率的编程,正在极大地减慢我的程序的速度!

我的问题是:如何检查才能使用If而不是Try?我将当前代码放在下面,然后列出我已经尝试过的解决方案。

    Public Shared Function GetSomeInfo() As List(Of String)
        Dim ret As New List(Of String)
        Dim sq As New Management.SelectQuery("Win32_Processor")
        Dim mos As New Management.ManagementObjectSearcher(sq)
        For Each info As Management.ManagementObject In mos.Get()
            ret.Add(TryQuery(info, "Name"))
            ret.Add(TryQuery(info, "Caption")) 'this query may result in Nothing somewhere...
        Next
        Return ret
    End Function

    Private Shared Function TryQuery(ByRef info As
            Management.ManagementObject, ByVal strID As String) As String
        Try
            Return strID & ": " & info(strID).ToString 'exception obviously thrown here...but WHERE?
        Catch ex As NullReferenceException
            Return String.Empty
        Catch ex As Management.ManagementException
            Return String.Empty
        End Try
    End Function

因此,这是我尝试过使用Try尝试解决的问题:
If Not info Is Nothing Then ...仍然导致一些未捕获的异常
If Not info(strID) Is Nothing Then ...在某处仍然有异常
If Not info.Equals(Nothing) Then ...绝望
If Not Info(strID).ToString Is Nothing ... :(

我根本不知道在哪里检查在WMI查询中引发的此异常。任何见识将不胜感激。谢谢!

最佳答案

根据您的描述,似乎对于给定的WMI类,虽然属性名称可能被列为现有属性,但是WMI PropertyData项不适用于给定的属性名称。蛮力方法应该通过迭代适当的PropertyDataCollection来避免产生“未找到”异常。

Private Shared Function TryQuery(ByRef info As ManagementObject, ByVal strID As String) As String
    Dim ret As String = String.Empty
    Dim propDatas As PropertyDataCollection
    If strID.StartsWith("__") Then
        ' system property, ref: https://msdn.microsoft.com/en-us/library/system.management.managementbaseobject.systemproperties(v=vs.110).aspx
        propDatas = info.SystemProperties
    Else
        ' object properties: ref: https://msdn.microsoft.com/en-us/library/system.management.managementbaseobject.properties(v=vs.110).aspx
        propDatas = info.Properties
    End If
    For Each data As PropertyData In propDatas
        If data.Name.Equals(strID, StringComparison.InvariantCultureIgnoreCase) Then
            ret = If(data.Value, String.Empty).ToString
            Exit For
        End If
    Next
    Return ret
End Function

而且,大多数WMI对象都是Disposable,应进行相应处理。
Public Shared Function GetSomeInfo() As List(Of String)
    Dim ret As New List(Of String)
    Dim sq As New Management.SelectQuery("Win32_Processor")
    Using mos As New Management.ManagementObjectSearcher(sq)
        Using objects As ManagementObjectCollection = mos.Get
            For Each info As Management.ManagementObject In objects
                Using info
                    ret.Add(TryQuery(info, "Name"))
                    ret.Add(TryQuery(info, "Caption")) 'this query may result in Nothing somewhere...
                End Using
            Next
        End Using
    End Using
    Return ret
End Function

编辑:为了提供一点保证,这种技术是有效的,您可以检查source code for the indexer on the ManagementBaseObject。该方法调用:
public Object GetPropertyValue(string propertyName)
{
    if (null == propertyName)
        throw new ArgumentNullException ("propertyName");

    // Check for system properties
    if (propertyName.StartsWith ("__", StringComparison.Ordinal))
        return SystemProperties[propertyName].Value;
    else
        return Properties[propertyName].Value;
}

您可以看到它检索到的属性类似于我提供的代码。问题是,如果ProdertyDataCollection类找不到匹配的属性名称,则将引发“未找到”错误。

关于.net - 检查WMI ManagementObject查询是否为Nothing,而不是使用Try/Catch?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50351873/

10-13 09:05