In my program, I am using the the WMI interface to query lots of information about the hardware that the program is running on. I'm then taking that information and putting it into a list to help with displaying it later, but not much else is done beyond that at the moment. This method so far has worked out pretty well, but there is one major issue: sometimes the query is/returns (don't know which one yet!) Nothing
and results in a NullReferenceException
.
Now, obviously I can wrap it in a Try/Catch and be on my merry way. However, I would like to avoid doing this because I will be querying hundreds of bits of information, and hundreds of them may result in an exception. This is just sloppy programming and is slowing my program down significantly!
My questions is: What do I check in order to use an If
instead of a Try
? I will put my current code below and then list the solutions I have already tried.
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
So, here's what I've tried in order to attempt and get around using this Try
:
If Not info Is Nothing Then ...
Still resulted in some uncaught exception
If Not info(strID) Is Nothing Then ...
Still got an exception somewhere
If Not info.Equals(Nothing) Then ...
Desperation
If Not Info(strID).ToString Is Nothing ...
:(
I simply have no idea where to check for this exception being throwing within the WMI query. Any insight would be appreciated. Thanks!
Based on your description, it appears that although a property name may be listed as existing for a given WMI class, but a 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
Also, most of the WMI objects are Disposable
and should be handled accordingly.
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
Edit: To provide a bit of assurance that this technique is valid, you can inspect the source code for the indexer on the ManagementBaseObject. This method calls:
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;
}
You can see that this retrieves the property similar to the code I have provided. The issue is that the ProdertyDataCollection class will throw a "Not Found" error if if it can not find a matching property name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With