检查 WMI ManagementObject 查询是否为 Nothing 而不是使用 Try/Catch?
Check if WMI ManagementObject query is Nothing instead of using a Try/Catch?
在我的程序中,我使用 WMI 接口查询有关程序 运行 所在硬件的大量信息。然后我会获取这些信息并将其放入列表中以帮助稍后显示它,但目前除此之外没有做太多其他事情。到目前为止,这种方法运行良好,但存在一个主要问题:有时查询 is/returns(还不知道是哪一个!)Nothing
并导致 NullReferenceException
。
现在,显然我可以将它包裹在 Try/Catch 中并开始我的快乐之旅。但是,我想避免这样做,因为我将查询数百位信息,而其中数百位可能会导致异常。这只是草率的编程,正在显着降低我的程序速度!
我的问题是:要使用 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 查询中抛出的异常。任何见解将不胜感激。谢谢!
我强烈怀疑问题出在这个表达式导致 Nothing
:
info(strID)
到目前为止,检查该表达式结果的现有代码中的所有地方都只在调用 .ToString()
之后才这样做,即:info(strID).ToString()
。因此它试图调用 Nothing
对象上的方法。您可以这样修复它:
Private Shared Function TryQuery(ByRef info As
Management.ManagementObject, ByVal strID As String) As String
If info Is Nothing OrElse strID Is Nothing Then Return String.Empty
Dim result = info(strID)
If result Is Nothing Then Return String.Empty
Return String.Format("{0}: {1}", strID, result)
End Function
根据您的描述,虽然 属性 名称可能被列为给定 WMI class 的现有名称,但 WMI PropertyData item is not available for the given property name. A brute force approach should work to avoid generating a "Not Found" exception by iterating the proper 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 class 如果找不到匹配的 属性 名称,将抛出 "Not Found" 错误。
在我的程序中,我使用 WMI 接口查询有关程序 运行 所在硬件的大量信息。然后我会获取这些信息并将其放入列表中以帮助稍后显示它,但目前除此之外没有做太多其他事情。到目前为止,这种方法运行良好,但存在一个主要问题:有时查询 is/returns(还不知道是哪一个!)Nothing
并导致 NullReferenceException
。
现在,显然我可以将它包裹在 Try/Catch 中并开始我的快乐之旅。但是,我想避免这样做,因为我将查询数百位信息,而其中数百位可能会导致异常。这只是草率的编程,正在显着降低我的程序速度!
我的问题是:要使用 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 查询中抛出的异常。任何见解将不胜感激。谢谢!
我强烈怀疑问题出在这个表达式导致 Nothing
:
info(strID)
到目前为止,检查该表达式结果的现有代码中的所有地方都只在调用 .ToString()
之后才这样做,即:info(strID).ToString()
。因此它试图调用 Nothing
对象上的方法。您可以这样修复它:
Private Shared Function TryQuery(ByRef info As
Management.ManagementObject, ByVal strID As String) As String
If info Is Nothing OrElse strID Is Nothing Then Return String.Empty
Dim result = info(strID)
If result Is Nothing Then Return String.Empty
Return String.Format("{0}: {1}", strID, result)
End Function
根据您的描述,虽然 属性 名称可能被列为给定 WMI class 的现有名称,但 WMI PropertyData item is not available for the given property name. A brute force approach should work to avoid generating a "Not Found" exception by iterating the proper 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 class 如果找不到匹配的 属性 名称,将抛出 "Not Found" 错误。